【问题标题】:Force Entity Framework to update several records in one round trip.强制实体框架在一次往返中更新多个记录。
【发布时间】:2016-07-07 14:05:15
【问题描述】:

我必须更新 EF 中的多条记录,我想出了以下两种方法:

方法一:ExecuteSqlCommand(直接SQL)

customDB.Database.ExecuteSqlCommand(
@"UPDATE  dbo.UserInfo
SET     dbo.UserInfo.Email = dbo.IAMUser.Email,
        dbo.UserInfo.Mobile = dbo.IAMUser.Phone
FROM    dbo.UserInfo
        INNER JOIN dbo.IAMUserMapping ON dbo.UserInfo.UserID = dbo.IAMUserMapping.fUserId
        INNER JOIN dbo.IAMUser ON IAMUser.IAMID = IAMUserMapping.fIAMID
WHERE   dbo.IAMUser.IAMID = @iamid ", new SqlParameter("@iamid", SqlDbType.UniqueIdentifier) { Value = IAMID });

方法二:Linq foreach:

var ui = from userInfo in customDB.UserInfo
     join userMapping in customDB.IAMUserMapping 
         on userInfo.UserID equals userMapping.fUserId
     join iamUser in customDB.IAMUser 
         on userMapping.IAMUser.IAMID equals iamUser.IAMID
     where iamUser.IAMID == IAMID
     select new
     {
         userInfo.UserID,
         iamUser.Email,
         iamUser.Phone
     };

foreach (var x1 in ui)
{
    var u = new UserInfo
    {
        UserID = x1.UserID,
        Email = x1.Email,
        Mobile = x1.Phone
    };
    customDB.UserInfo.Attach(u);
    var entry = customDB.Entry(u);
    entry.Property(e => e.Email).IsModified = true;
    entry.Property(e => e.Mobile).IsModified = true;
}
customDB.SaveChanges();

方法 #1 是最有效的,产生单个 SQL 查询。

方法 #2 在 SQL Server 方面同样有效,但它会产生更多到服务器的往返行程。 1 选择以获取记录,然后为每条更新的记录进行 1 次更新。

如果数据库中的任何内容发生更改,方法 #2 将给出编译时错误,而 #1 将给出运行时错误。

在此类情况下,人们认为最佳做法是什么?

有什么方法可以两全其美?

【问题讨论】:

  • SO 的标记中有一个众所周知的错误,它会导致编号列表中的代码格式出现问题。我刚刚拒绝了一个使情况变得更糟的编辑,所以我现在无法修复。只需edit 并摆脱编号列表并将您的代码正确格式化为代码。
  • 我在贴子上看到的,用前面的写法修好了。 Ty 进行编辑。
  • 最佳实践使这个问题在 Stack Overflow 上偏离了主题(基于意见,并且很难回答,因为这取决于您权衡两种方法的权衡)。 还有其他优化此查询的方法吗? 在这里问一个更好的问题,但即便如此,人们可能会认为 CodeReview 更合适。
  • 问题更多的是这两种方法是否是最好的方法,或者是否有第三种方法更好。
  • 在这种情况下,您的第一种方法是最好的,尤其是当它涉及大量记录时。另一种方法是使用存储过程,其结果与您的第一个示例非常相似。

标签: c# entity-framework linq


【解决方案1】:

使用第一种方法时,您可能面临的问题将更加关键且难以解决,例如重命名/重组实体时。编译时错误要好得多,比运行时错误更容易解决。

另外,我不确定 ExecuteSqlCommand 方法是如何工作的,但看起来这段代码容易受到 SQL 注入的攻击。 所以,我肯定会选择 linq 方法。

【讨论】:

  • ExecuteSqlCommand 是安全的,只要你使用参数。如果使用分析器进行跟踪,生成的 SQL 是相等的。
  • 我不同意第 1 点,但这更多的是见仁见智。在第 2 点,它是参数化的,因此没有 sql 注入的风险。在 OPs 示例中,代码甚至传入了一个 SqlParameter 实例来说明它。
  • 这取决于你需要什么,正如有人回答你可以做一个存储过程,现在如果你想消费大量数据,这很简单你可以把它放到一个托管的后台运行晚上做交易的人比较少。但如果人们知道如何使用本机 SqlConnection、SqlCommand 等,则可以肯定你可以参数化。
猜你喜欢
  • 1970-01-01
  • 2017-07-11
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
相关资源
最近更新 更多