我认为也许最初的问题太过冗长,有太多不必要的细节,所以这是我试图简化。
我正在寻找一种方法来执行以下任何的操作。我只需要做一个,而不是全部。如果有人知道其中一个的答案,请回复。那么,是否可以在Linq to SQL中执行以下任何操作:
通过DataContext
或ExecuteQuery
从ExecuteMethodCall
中提取实体而不跟踪这些实体?
调用ExecuteQuery
或ExecuteMethodCall
并保证我始终收到从数据库中检索到的结果的新副本,即使这些实体已被检索并且已经在身份缓存中?
指示Linq to SQL不对特定实体类型执行任何更改跟踪 - 但仍允许对其他类型进行更改跟踪?
限制:
Refresh
方法是不可能的;实体数量非常大,这将成为一场性能灾难。
我不能简单地将ObjectTrackingEnabled
设置为false
,因为DataContext
在执行查询后不允许将其设置回true
,而我确实需要一些要跟踪的实体。
我也不能丢弃原来的DataContext
并使用新的DataContext
;我需要能够在交易过程中做到这一点。
这开始成为一个严重的问题,我真的认为默认行为是错误的。如果我执行临时查询或存储过程,我希望我收到的结果是所述查询返回的确切结果。它才有意义;如果我想要旧的陈旧实体,为什么我会回到数据库来获取它们?
目前,我的解决方法是(a)专门为查询创建一个新的[Table]
并覆盖事务隔离级别,或者(b)使返回类型成为与“DTO”相同的“DTO”实体,但没有{{1}}属性,并使用AutoMapper将其映射到原始实体。这两件事看起来都像是可怕的黑客。
非常感谢任何人对这个难题的任何建议。
答案 0 :(得分:3)
我已经设法为这个问题提出了一个可行的长期解决方法。它并不是非常理想,但到目前为止它的应用相对来说并不那么容易,而且远不如替代品那么可怕。
由于这些查询无论如何都是纯SQL - 它们对于内联SQL都是ExecuteQuery
或对于存储过程都是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
表现得更好,那仍然会更好。
答案 1 :(得分:0)
如果从LINQ查询为结果构造新对象,则不会对其进行更改跟踪。因此,您可以使用现有的DataContext来加载您不需要更新的值,例如here中的代码):
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实际上是一个工作单元级别集合,而不是整个世界。因此,为您的只读类型数据和可更新数据使用单独的DataContexts非常有意义(除非您无法预测哪个是提前的,我想)。