Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用linq到SQL更新特定列_C#_Linq To Sql - Fatal编程技术网

C# 使用linq到SQL更新特定列

C# 使用linq到SQL更新特定列,c#,linq-to-sql,C#,Linq To Sql,我有一个需要更新的数千个GUID(超过100k)记录的本地列表 现在我使用的是简单的: foreach(var id in GUIDs) { var objToUpdate = dataContext.table.Single(o=>o.id==id); objToUpdate.val1=... objToUpdate.val2=... ... } dataContext.SubmitChanges(); 这个解决方案非常慢。每次调用单个方法时,都会

我有一个需要更新的数千个GUID(超过100k)记录的本地列表

现在我使用的是简单的:

foreach(var id in GUIDs)
{
    var objToUpdate = dataContext.table.Single(o=>o.id==id);

    objToUpdate.val1=...
    objToUpdate.val2=...
    ...


}
dataContext.SubmitChanges();
这个解决方案非常慢。每次调用单个方法时,都会从数据库中检索整个记录(我不需要它,因为我正在覆盖除主键之外的所有数据)

有没有办法只检索我真正需要的两列?(主键和另一列)

当我这样做的时候:

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倍(取决于数据):

但有了这个,我无法更新记录

你有什么建议吗?
关于

要从特定列获取值,请使用此查询:

var objToUpdate = (from o in dataContext.Table
                   where o.id == guid
                   select new {o.Column1, o.Column2, ...}).Single();
selectnew{…}
语法很重要,因为它投射到一个匿名类型中,而该类型不属于上下文跟踪的一部分。如果获得的对象是上下文跟踪的一部分,那么在接下来使用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时,将更新正确的行。

尝试使用批量更新,在您的情况下,您需要使用存储过程。我建议使用秒表来确定您的代码中哪一行是耗时的,然后您可以从中改进。看看这里:我认为,这是一个好方法,我需要使用attach。。以下链接:但我无法使其工作。当我附加时,我得到一个错误:无法添加具有已在使用的键的实体。@mateuszwdowiak您引用的devio文章只表明您必须首先引入旧值。这里的文档显示,如果您可以在不使用旧值的情况下计算所有新值并知道主键,则不需要这样做。谢谢,这就解决了问题。我的情况还有另一个问题。我是使用以下语句检索数据的:(从dataContext.fn_getGuidsFromString(String.Join(“,GUIDs))中的id=o.PrimaryKey选择o的dataContext.table中的Join o)使用相同的dataContext,检索到的项已附加。这就是我出错的原因:“无法添加具有已在使用的密钥的实体。”当我将其更改为匿名对象时,解决了这个问题。谢谢你的建议!我刚刚发现,现在我在连接上没有例外。我遇到一个异常:当我尝试提交更改时,未找到或更改行。。所以这仍然没有解决。@mateuszwdowiak Attach确实假设数据库中存在具有该主键的记录。在调用SubmitChanges之前,该记录是否可能已经存在并被删除?您可以尝试将SubmitChanges()移动到foreach循环中,并逐步进行几次迭代,以查看是针对每一行还是某些行引发此错误。内部异常中是否有其他信息?您是否有权访问任何SQL日志,以显示失败的操作?
 dataContext.SubmitChanges();