У меня есть метод, что я хочу быть "транзакционным" в абстрактном смысле. Это называет два метода, которые, оказывается, делают материал с базой данных, но этот метод не знает это.
public void DoOperation()
{
using (var tx = new TransactionScope())
{
Method1();
Method2();
tc.Complete();
}
}
public void Method1()
{
using (var connection = new DbConnectionScope())
{
// Write some data here
}
}
public void Method2()
{
using (var connection = new DbConnectionScope())
{
// Update some data here
}
}
Поскольку в реальном выражении TransactionScope
средства, что транзакция базы данных будет использоваться, у нас есть проблема, где это могло способствоваться Распределенной транзакции, если мы получаем два различных соединения от пула.
Я мог зафиксировать это путем обертывания DoOperation()
метод в ConnectionScope:
public void DoOperation()
{
using (var tx = new TransactionScope())
using (var connection = new DbConnectionScope())
{
Method1();
Method2();
tc.Complete();
}
}
Я сделал DbConnectionScope
самостоятельно для просто такой цели, так, чтобы я не передавал объекты соединения подметодам (это - более изобретенный пример, чем моя реальная проблема). Я получил идею из этой статьи: http://msdn.microsoft.com/en-us/magazine/cc300805.aspx
Однако мне не нравится это обходное решение, как это означает DoOperation
теперь имеет знание, что методы, которые это называет, могут использовать соединение (и возможно другое соединение каждый). Как я мог осуществить рефакторинг это для решения вопроса?
Одна идея, о которой я думаю, создает более общее OperationScope
, так, чтобы при объединениях с пользовательским образом жизни замка Windsor я записал, будет означать любой компонент, который требуют от контейнера с OperationScopeLifetyle
будет всегда получать тот же экземпляр того компонента. Это действительно решает проблему потому что OperationScope
более неоднозначно, чем DbConnectionScope
.
Я вижу противоречивые требования здесь.
С одной стороны, вы не хотите Dooperation
, чтобы иметь какое-либо осознание того факта, что соединение базы данных используется для его подпрограммы.
С другой стороны, это четко осознает этот факт, потому что он использует A Skresscope
.
Я могу понять, что вы получаете, когда вы говорите, что хотите, чтобы он был транзакционным в абстрактном смысле , но мой взять на себя это то, что он практически невозможно (нет, царапает это полностью невозможно) описать транзакцию в таких абстрактных терминах. Давайте просто скажем, у вас есть такой класс:
class ConvolutedBusinessLogic
{
public void Splork(MyWidget widget)
{
if (widget.Validate())
{
widgetRepository.Save(widget);
widget.LastSaved = DateTime.Now;
OnSaved(new WidgetSavedEventArgs(widget));
}
else
{
Log.Error("Could not save MyWidget due to a validation error.");
SendEmailAlert(new WidgetValidationAlert(widget));
}
}
}
Этот класс делает по крайней мере две вещи, которые, вероятно, не могут быть откатываться от спины (устанавливая свойство класса и выполнение обработчика событий, что может например, Cascade-Update Управление в форме) и, по крайней мере, еще два веща, что определенно не может быть откатано (присоединяется к файлу журнала где-то и отправка адресата электронной почты).
Возможно, это кажется надуманным примером, но это на самом деле моя точка зрения; Вы не можете лечить анакопс
как «черный ящик». Область применения на самом деле зависимость, как и любой другой; Deskscope
просто обеспечивает удобную абстракцию для единицы работы, которая не всегда может быть уместной, потому что она на самом деле не обернет соединение с базой данных и не может предсказать будущее. В частности, обычно это не подходит, когда одна логическая операция должна охватывать более одного соединения с базой данных, будь то эти соединения к той же базе данных или разных. Он пытается справиться с этим случаем, конечно, но, как вы уже узнали, результат является подактивным.
То, как я его вижу, у вас есть несколько разных вариантов:
сделать явную то, что Method1
и Method2
требуют соединения, имея их принимать параметр подключения, или путем рефакторизации их в класс, который принимает зависимость соединения (конструктор или свойство). Таким образом, соединение становится частью контракта , поэтому Метод1
больше не знает слишком много - он точно знает, что он должен знать в соответствии с дизайном.
Примите, что ваша метод
имеет осознание метода
и метода2
. На самом деле, Нет ничего плохого в этом! Это правда, что вы не хотите полагаться на детали реализации некоторых будущих звонков, но прямых зависимостей в абстракции, как правило, считаются нормальными; Это Регистрация зависимости зависимостей, которые вы должны быть обеспокоены, вроде бы, когда какой-то класс глубоко в модели домена пытается обновить управление пользовательским интерфейсом, о котором нет бизнеса, зная в первую очередь.
Используйте более прочную единицу работы Узор (также: здесь ). Это становится все более популярным, и он, по и BARE, направление Microsoft вошел с LINQ к SQL и EF ( DataContext
/ ObjectContext
в основном реализации UOW). Эти рукава в колодете с Di Framework и, по существу, снимают вас о необходимости беспокоиться о том, когда транзакции начинаются и заканчиваются, и как должен произойти доступ к данным (термин - это «нежеливание настойчивости»). Это, вероятно, потребует значительных перепроектов вашего дизайна, но фунт за фунт, он будет самым простым, чтобы поддерживать долгосрочные.
Надеюсь, один из тех помогает вам.
Я предпочитаю избегать скриптов в середине своей страницы и должен был использовать их (все чаще), чтобы избежать последовательностей при использовании в коде JavaScript. Я хотел Язык выражения (EL) способ избежать последовательности. Я создал очень маленький пользовательский tallib, который я использую только для этой цели:
Utilities.java:
package com.mycom.taglibs;
import org.apache.commons.lang.StringEscapeUtils;
public class Utilities {
public static String escapeJS(String value) {
return StringEscapeUtils.escapeJavaScript(value);
}
}
mytaglib.tld:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>My Tag Library</description>
<display-name>Tag Utils</display-name>
<tlib-version>1.1</tlib-version>
<short-name>myt</short-name>
<function>
<description>
JavaScript Escape function
</description>
<name>escapeJS</name>
<function-class>com.mycom.taglibs.Utilities</function-class>
<function-signature>java.lang.String escapeJS(java.lang.String)</function-signature>
</function>
</taglib>
И, на странице JSP:
<%@ taglib prefix="myt" uri="/WEB-INF/mytaglib.tld" %>
The escaped string is: ${myt:escapeJS(variableHoldingTheString)}
-121--1299625- Следующие сценарии написаны в sybase sql. Возможно, потребуется выполнить незначительные изменения в соответствии с сервером БД.
1 проблемы.
create table #connections (
my_user varchar(10) not null ,
knows varchar(10) not null ,
CONSTRAINT connection_pk PRIMARY KEY CLUSTERED ( my_user, knows)
)
create table #traversed (id varchar(10) primary key)
insert into #connections VALUES ('UserA','UserB')
insert into #connections VALUES ('UserB','UserA')
insert into #connections VALUES ('UserB','UserC')
insert into #connections VALUES ('UserC','UserB')
insert into #connections VALUES ('UserC','UserD')
insert into #connections VALUES ('UserD','UserC')
insert into #connections VALUES ('UserD','UserF')
insert into #connections VALUES ('UserF','UserD')
DECLARE @str_sql varchar(200)
DECLARE @str_order varchar(60)
declare @start varchar(10)
set @start = ('UserD')
declare @end varchar(10)
set @end = ('UserA')
if (@start >= @end)
set @str_order = " order by id desc"
else
set @str_order = " order by id asc"
INSERT INTO #traversed VALUES (@start)
WHILE (select count(*) from #traversed where id = @end) = 0
BEGIN
INSERT INTO #traversed (id)
SELECT DISTINCT knows
FROM #connections e JOIN #traversed p ON p.id = e.my_user
WHERE e.knows NOT IN (SELECT id FROM #traversed)
AND e.knows between (select case when @start < @end then @start else @end end)
and (select case when @start < @end then @end else @start end)
END
set @str_sql = "SELECT #traversed.id FROM #traversed" + @str_order
exec (@str_sql)
Проблема 2.
create table #connections (
my_user varchar(10) not null ,
knows varchar(10) not null ,
CONSTRAINT connection_pk PRIMARY KEY CLUSTERED ( my_user, knows)
)
create table #traversed (id varchar(10) primary key)
insert into #connections VALUES ('UserA','UserB')
insert into #connections VALUES ('UserB','UserA')
insert into #connections VALUES ('UserB','UserC')
insert into #connections VALUES ('UserC','UserB')
insert into #connections VALUES ('UserC','UserD')
insert into #connections VALUES ('UserD','UserC')
insert into #connections VALUES ('UserD','UserF')
insert into #connections VALUES ('UserF','UserD')
declare @start varchar(10)
set @start = ('UserB')
declare @higher_counter int
declare @lower_counter int
set @higher_counter = 0
set @lower_counter = 0
INSERT INTO #traversed VALUES (@start)
WHILE (@higher_counter < 3)
BEGIN
INSERT INTO #traversed (id)
SELECT DISTINCT knows
FROM #connections e JOIN #traversed p ON p.id = e.my_user
WHERE e.knows NOT IN (SELECT id FROM #traversed)
AND e.knows > @start
set @higher_counter = @higher_counter +1
END
WHILE (@lower_counter < 3)
BEGIN
INSERT INTO #traversed (id)
SELECT DISTINCT knows
FROM #connections e JOIN #traversed p ON p.id = e.my_user
WHERE e.knows NOT IN (SELECT id FROM #traversed)
AND e.knows < @start
set @lower_counter = @lower_counter +1
END
SELECT #traversed.id FROM #traversed
-121--1645612- Можно ли передать/зачислить транзакцию в БД и полностью удалить ее из кода?