1

我认为最初的问题可能过于冗长,包含太多不必要的细节,所以这是我简化的尝试。

我正在寻找一种方法来执行以下任何操作。我只需要做一个,而不是全部。如果有人知道其中之一的答案,请回复。那么,是否可以在 Linq to SQL 中执行以下任何操作:

  • DataContext将实体从通孔中拉出ExecuteQuery还是ExecuteMethodCall不跟踪这些实体?

  • 调用ExecuteQueryExecuteMethodCall保证我总是收到从数据库检索到的结果的新副本,即使这些实体已经被检索并且已经在身份缓存中?

  • 指示 Linq to SQL 不要对特定实体类型执行任何更改跟踪 - 但仍允许对其他类型进行更改跟踪?

限制:

  • Refresh方法是不可能的;实体的数量很大,这将成为性能灾难。

  • 我不能简单地设置ObjectTrackingEnabledfalse,因为DataContext不允许true在执行查询后将其设置回,并且我确实需要跟踪一些实体。

  • 我也不能扔掉原来的DataContext并使用一个新的;我需要能够在交易过程中做到这一点。


这开始成为一个严重的问题,我真的认为默认行为是错误的。如果我执行临时查询或存储过程,我希望收到的结果与所述查询返回的结果完全相同。这才有意义;如果我想要旧的、陈旧的实体,我为什么要返回数据库来获取它们?

目前,我的解决方法是(a)DataContext专门为查询创建一个新的并覆盖事务隔离级别,或者(b)将返回类型设置为在各个方面都与实体相同但没有[Table]属性,并使用 AutoMapper 将其映射到原始实体。这两个似乎都是可怕的黑客。

非常感谢任何人对这个难题的任何建议。

4

2 回答 2

3

我已经设法为这个问题提出了一个可行的长期解决方法。它并不完美,但到目前为止使用起来相对轻松,而且远没有其他替代方案那么可怕。

因为这些查询无论如何都是纯 SQL ——它们都是ExecuteQuery用于内联 SQL 或ExecuteMethodCall存储过程的——我决定只下拉到“原始”ADO.NET 以应对我不想DataContext知道某些实体的情况。

当然,不得不处理来自 的一堆IDbCommand实例和手动映射是很可怕的IDataReader,所以今天早上我花了几个小时编写一个库来为我完成大部分繁重的工作,暴露了一个“流利的”(我松散地使用术语)包装器IDbCommand,一个自动LinqDataReaderMapper使用的,MetaModel因此我可以使用我现有的实体而无需修改,以及一堆重载的扩展方法,可以更快地编写更简单的查询。

在一天结束时,我正在写这样的东西:

var results = context.Connection
    .Command("SELECT Column1, Column2 FROM Table " +
             "WHERE FilterColumn1 = @Param1 AND FilterColumn2 = @Param2")
    .Parameters(
        p => p.Name("Param1").Value(someValue),
        p => p.Name("Param2").Value(someOtherValue))
    .ExecuteReader()
    .MapWith(context.Mapping).To<MyEntity>();

或者只是这样:

var results = context
    .ExecuteQueryRaw<MyEntity>(CommandType.StoredProcedure, "SomeProc",
        new { Param1 = someValue, Param2 = someOtherValue });

我不打算为它发布整个代码——它很长,我认为这只是一个很大的tl;dr在这一点上——但主要的想法是这些都给了我一个IEnumerable<MyEntity>,因为它们是直接从 复制IDataReader,它们本质上是分离的实体 - 对DataContext它们没有直接的了解,因此既不能拦截结果,也不能在事后跟踪它们。

所以,问题部分解决了,尽管如果我能让它DataContext自己表现出来会更好。

于 2010-02-05T20:55:54.363 回答
0

如果您为 LINQ 查询的结果构造一个新对象,它将不会被跟踪更改。因此,您可以使用现有的 DataContext 来加载您知道不需要更新的值,就像这样(代码来自这里):

using (NorthwindDataContext context = new NorthwindDataContext())
{
  var a = from c in context.Categories
  select new Category
  {
    CategoryID = c.CategoryID,
    CategoryName = c.CategoryName,
    Description = c.Description
  };
}

我认为这本质上就是您在答案中的第二个示例中所拥有的,我只想确认它有效并且不是一个坏主意。

另外,我的理解是,在任何情况下都不应该使用单个海量 DataContext ;DataContext 实际上是一个 Unit-of-Work 级别的集合,而不是整个世界。因此,为您的只读类型数据和可更新数据使用单独的 DataContext 非常有意义(除非您无法提前预测哪个是哪个,我想)。

于 2010-02-05T21:09:32.590 回答