Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.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# 实体框架更新/插入多个实体_C#_Sql Server_Entity Framework - Fatal编程技术网

C# 实体框架更新/插入多个实体

C# 实体框架更新/插入多个实体,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,只是我要完成的事情的一点概要。 我们在应用程序中保留远程数据库(第三方)的本地副本。要下载信息,我们使用api。 目前,我们按照时间表下载信息,然后将新记录插入本地数据库或更新现有记录。 下面是它目前的工作原理 public void ProcessApiData(List<Account> apiData) { // get the existing accounts from the local database List<Account> exi

只是我要完成的事情的一点概要。 我们在应用程序中保留远程数据库(第三方)的本地副本。要下载信息,我们使用api。 目前,我们按照时间表下载信息,然后将新记录插入本地数据库或更新现有记录。 下面是它目前的工作原理

public void ProcessApiData(List<Account> apiData)
{
     // get the existing accounts from the local database
     List<Account> existingAccounts = _accountRepository.GetAllList();

     foreach(account in apiData)
     {
         // check if it already exists in the local database
         var existingAccount = existingAccounts.SingleOrDefault(a => a.AccountId == account.AccountId);

         // if its null then its a new record
         if(existingAccount == null)
         {
             _accountRepository.Insert(account);
             continue;
         }

         // else its a new record so it needs updating
         existingAccount.AccountName = account.AccountName;

         // ... continue updating the rest of the properties
     }

     CurrentUnitOfWork.SaveChanges();
}
public void ProcessApiData(列表
但它似乎专注于批量更新具有相同值的单个属性,或者我可以这么说
任何关于如何改进这一点的建议都会非常好。我对c#还是相当陌生,所以我仍在寻找最好的方法

我正在使用.net 4.5.2和实体框架6.1.3以及MSSQL 2014作为后端数据库

  • 假设apiData中的类与实体相同,您应该能够使用
    Attach(newAccount,originalAccount)
    更新现有实体
  • 对于批量插入,我使用
    AddRange(ListofNewEntities)
    。如果要插入大量实体,建议对它们进行批处理。此外,您可能希望在每个批上处理并重新创建
    DbContext
    ,这样它就不会占用太多内存

    var accounts = new List<Account>();
    var context = new YourDbContext();
    context.Configuration.AutoDetectChangesEnabled = false;
    
    foreach (var account in apiData)
    {
        accounts.Add(account);
        if (accounts.Count % 1000 == 0) 
        // Play with this number to see what works best
        {
            context.Set<Account>().AddRange(accounts);
            accounts = new List<Account>();
            context.ChangeTracker.DetectChanges();
            context.SaveChanges();
            context?.Dispose();
            context = new YourDbContext();
        }
    }
    
    context.Set<Account>().AddRange(accounts);
    context.ChangeTracker.DetectChanges();
    context.SaveChanges();
    context?.Dispose();
    

    var accounts=使用表达式树的解决方案的新列表。

    列表与字典

    如果实体不存在,则每次都签入一个列表。您应该创建一个字典来提高性能

    var existingAccounts = _accountRepository.GetAllList().ToDictionary(x => x.AccountID);
    
    Account existingAccount;
    
    if(existingAccounts.TryGetValue(account.AccountId, out existingAccount))
    {
        // ...code....
    }
    
    添加与添加范围

    当您添加多个记录时,您应该了解Add与AddRange的性能

    • 添加:添加每条记录后调用检测更改
    • AddRange:添加所有记录后调用检测更改

    因此,在10000个实体中,Add方法仅在上下文中添加实体就花费了875倍的时间

    要解决此问题,请执行以下操作:

  • 创建一个列表
  • 将实体添加到列表中
  • 在列表中使用AddRange
  • 保存更改
  • 完成了
  • 在您的情况下,需要为存储库创建InsertRange方法

    EF扩展

    没错。此库使用相同的值更新所有数据。这不是您要查找的

    免责声明:我是项目的所有者

    如果您想显著提高性能,此库可能非常适合您的企业

    您可以轻松执行以下操作:

    • 批量保存更改
    • 隔板
    • 批量更新
    • 批量删除
    • 大合并
    例如:

    public void ProcessApiData(List<Account> apiData)
    {
        // Insert or Update using the primary key (AccountID)
        CurrentUnitOfWork.BulkMerge(apiData);
    }
    
    public void ProcessApiData(列出apiData)
    {
    //使用主键(AccountID)插入或更新
    CurrentUnitOfWork.BulkMerge(apiData);
    }
    
    对于EFCore,您可以使用此库:

    对于EF 6,这个:

    两者都使用批量操作扩展
    DbContext
    ,并具有相同的语法调用:

    context.BulkInsert(entitiesList);
    context.BulkUpdate(entitiesList);
    context.BulkDelete(entitiesList);
    

    EFCore版本还有另外一个
    BulkInsertOrUpdate
    方法。

    AddRange不执行“Bulk Insert”,只需调用一次DetectChanges,就可以比add提高性能。谢谢@Hintham。我将此标记为可接受的答案,因为它对我获得最终解决方案帮助很大。没问题,很高兴它有所帮助