我有一个包含数千个GUID(超过100k)记录的本地列表,我需要更新。
现在我使用简单:
foreach(var id in GUIDs)
{
var objToUpdate = dataContext.table.Single(o=>o.id==id);
objToUpdate.val1=...
objToUpdate.val2=...
...
}
dataContext.SubmitChanges();
此解决方案非常慢。每当我调用Single方法时,整个记录都会从DB中检索出来(我不需要它,因为我会覆盖除主键之外的所有数据)。
有什么方法可以只检索我真正需要的两列吗? (主键,另一列)?
当我做这样的事情时:
dataContext.table.Select(o =>
new sqlRecord
{
PrimaryKey = o.PrimaryKey,
AnotherCol = o.AnotherCol
}
);
我收到错误:
Explicit construction of entity type '{0}' in query is not allowed.
使用存储过程不是一种选择。根据外部资源设置正确的数据值非常复杂。
var query = dataContext.table.Where(o => GUIDs.Contains(o.id));
foreach(var objToUpdate in query)
{
objToUpdate.val1 =...;
objToUpdate.val2 = ...;
}
dataContext.SubmitChanges();
这会产生错误,我使用超过2100个参数,而我有大量的GUID。
为此,我正在使用替代方案:
(from ids in dataContext.fn_getGuidsFromString(String.Join("", GUIDs)) join o in dataContext.table on ids.id equals o.PrimaryKey select o)
其中fn_getGuidsFromString是SQL中的表函数。这比使用where和Contains更好。
我的问题是这个效果太慢了。你必须知道,在这个表中有超过200列,其中一些是ntext,包含大量数据。
dataContext.table.Single(o=>o.id==id);
比这慢约20倍(取决于数据):
dataContext.table.Single(o=>o.id==id).select(o=>new {o.id, o.anotherCol});
但是我无法更新记录。
你有什么建议吗? 此致
答案 0 :(得分:0)
要从特定列获取值,请使用以下查询:
var objToUpdate = (from o in dataContext.Table
where o.id == guid
select new {o.Column1, o.Column2, ...}).Single();
select new {...}
语法很重要,因为它投射到不属于上下文跟踪的匿名类型。如果获得的对象是上下文跟踪的一部分,那么接下来使用Attach方法时会收到错误,因为您无法使用相同的主键跟踪两个对象,而Attach将添加一个带有主键。
现在,要更新数据库,只需使用更新的值并使用正确的主键创建实体的存根:
TableName stub = new TableName();
// One of these should be a primary key.
stub.val1 = ...;
stub.val2 = ...;
TableName.Attach(stub); // Will throw an exception if the row with this primary key is already being tracked in memory.
完成所有更改后,请致电
dataContext.SubmitChanges();
重要的是,如果不需要旧值并且主键都已知,则可以跳过用于引入旧行的查询。可以在不先查询数据库的情况下添加存根,然后在调用SubmitChanges时,将更新正确的行。