在事务范围中执行查询的通用方法

时间:2015-03-23 15:57:58

标签: c# generics transactionscope

我正在创建一个通用方法,它允许我在事务范围内包含数据库的每个操作。目前我的代码中有多个LINQ to SQL操作,例如:

var myVar = MyContext.First(c => c.Id == myId);

我现在拥有的是每个可能操作的通用方法,例如Count,First,FirstOrDefault,ToList等:

public static TSource FirstReadUncommitted<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate = null)
    {
        var transactionOptions = new TransactionOptions()
        {
            IsolationLevel = IsolationLevel.ReadUncommitted
        };
        TSource outputItem;
        using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
        {
            outputItem = predicate != null ? source.First(predicate) : source.First();
            scope.Complete();
        }
        return outputItem;
    }

但是,我想要一种更通用的方法,我可以以某种方式将我想要应用于查询的方法作为参数传递,如下所示:

public static TSource ReadUncommittedFunction<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate = null, Function????? function)
        {
            var transactionOptions = new TransactionOptions()
            {
                IsolationLevel = IsolationLevel.ReadUncommitted
            };
            TSource outputItem;
            using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
            {
                outputItem = predicate != null ? source.function(predicate) : source.function();
                scope.Complete();
            }
            return outputItem;
        }

这可能吗?函数参数的类型是什么?

在一个更复杂的方法中,我想向上面提到的方法发送一个要在我的范围内执行的操作列表(因为事务可能包含多个操作)。这可能吗?

public static TSource ReadUncommittedFunctions<TSource>(FunctionList functionList)
        {
            var transactionOptions = new TransactionOptions()
            {
                IsolationLevel = IsolationLevel.ReadUncommitted
            };
            TSource outputItem;
            using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
            {
                source.functionList.ElementAt(0)();
                source.functionList.ElementAt(1)();
                scope.Complete();
            }
            return outputItem;
        }

2 个答案:

答案 0 :(得分:0)

您可以尝试使用通用Func,如下所示:

public static TSource ReadUncommittedAction<TSource>(Func<TSource> func)
{
  var transactionOptions = new TransactionOptions()
  {
      IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
  };
  TSource outputItem;
  using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
  {
      outputItem = func();
      scope.Complete();
  }
  return outputItem;
}

然后:

ReadUncommittedAction<SomeClass>(() => 
{
    // as many actions as needed
    return new SomeClass();
});

答案 1 :(得分:0)

好。我想到了你想要的几种方法。

首先,我想您可以在范围内传递要在“源”上调用的函数的名称,并使用反射来调用正确的方法。很像这篇文章:

Calling a function from a string in C#

或者,您可以执行与谓词相同的操作...扩展'ReadUncommittedFunctions'函数以将额外的Func作为参数。 Func将范围和谓词作为输入,TSource作为输出。在Func中,您可以在范围上应用desidered操作并返回结果。然后'ReadUncommittedFunctions'将调用using块中的Func。

只是一个建议。