实体框架更新/插入多个实体 [英] Entity Framework update/insert multiple entities

查看:159
本文介绍了实体框架更新/插入多个实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  public void ProcessApiData(List< Account> apiData)
{
//从本地数据库获取现有帐户
列表< Account> existingAccounts = _accountRepository.GetAllList();

foreach(apiData中的帐户)
{
//检查本地数据库中是否已经存在
var existingAccount = existingAccounts.SingleOrDefault(a => a .AccountId == account.AccountId);

//如果它的null,那么它的一个新记录
if(existingAccount == null)
{
_accountRepository.Insert(account);
继续;
}

//其新的记录,因此需要更新
existingAccount.AccountName = account.AccountName;

// ...继续更新其他属性
}

CurrentUnitOfWork.SaveChanges();
}

这工作正常,但只是觉得这样可以改进。 p>


  1. 每个Entity都有一种方法,他们都做同样的事情(只是更新不同的属性)或插入不同的实体。有没有办法让这个更通用?

  2. 这似乎是很多数据库调用,还有Bulk这样做。我已经看过我看到的其他帖子中提到的这个软件包 https:// github。 com / loresoft / EntityFramework.Extended
    但它似乎专注于批量更新具有相同值的单个属性,或者我可以告诉。

关于我如何改进这一点的任何建议将是辉煌的。我还是相当新的c#,所以我仍然在寻找最好的办法。



我使用的是.net 4.5.2和实体框架6.1 .3以MSSQL 2014作为后端数据库

解决方案


  1. 假设apiData中的类是相同的作为您的实体,您应该可以使用 Attach(newAccount,originalAccount)来更新现有实体。

  2. 批量插入我使用 AddRange(listOfNewEntitities)。如果您有很多实体要插入,建议您对它们进行批处理。另外,您可能希望在每个批处理中重新配置并重新创建 DbContext ,以免使用太多的内存。

      var accounts = new List< Account>(); 
    var context = new YourDbContext();
    context.Configuration.AutoDetectChangesEnabled = false;
    foreach(apiData中的var account)
    {
    accounts.Add(account);
    if(accounts.Count%1000 == 0)
    //播放此号码以查看最有效的
    {
    context.Set< Account>()。AddRange帐户);
    accounts = new List< Account>();
    context.ChangeTracker.DetectChanges();
    context.SaveChanges();
    上下文?.Dispose();
    context = new YourDbContext();
    }
    }
    context.Set< Account>()。AddRange(accounts);
    context.ChangeTracker.DetectChanges();
    context.SaveChanges();
    上下文?.Dispose();


对于批量更新,在LINQ to SQL中。然而,图书馆和解决方案有待解决。参见例如

Just a bit of an outline of what i am trying to accomplish. We keep a local copy of a remote database (3rd party) within our application. To download the information we use an api. We currently download the information on a schedule which then either inserts new records into the local database or updates the existing records. here is how it currently works

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();
}

This works fine, however it just feels like this could be improved.

  1. There is one of these methods per Entity, and they all do the same thing (just updating different properties) or inserting a different Entity. Would there be anyway to make this more generic?
  2. It just seems like a lot of database calls, would there be anyway to "Bulk" do this. I've had a look at this package which i have seen mentioned on a few other posts https://github.com/loresoft/EntityFramework.Extended But it seems to focus on bulk updating a single property with the same value, or so i can tell.

Any suggestions on how i can improve this would be brilliant. I'm still fairly new to c# so i'm still searching for the best way to do things.

I'm using .net 4.5.2 and Entity Framework 6.1.3 with MSSQL 2014 as the backend database

解决方案

  1. Assuming that the classes in apiData are the same as your entities, you should be able to use Attach(newAccount, originalAccount) to update an existing entity.
  2. For bulk inserts I use AddRange(listOfNewEntitities). If you have a lot of entities to insert it is advisable to batch them. Also you may want to dispose and recreate the DbContext on each batch so that it's not using too much memory.

    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();
    

For bulk updates, there's not anything built in in LINQ to SQL. There are however libraries and solutions to address this. See e.g. Here for a solution using expression trees.

这篇关于实体框架更新/插入多个实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆