实体框架更新/插入多个实体 [英] Entity Framework update/insert multiple entities
问题描述
我们在我们的应用程序中保留远程数据库(第三方)的本地副本。要下载我们使用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>
- 每个Entity都有一种方法,他们都做同样的事情(只是更新不同的属性)或插入不同的实体。有没有办法让这个更通用?
- 这似乎是很多数据库调用,还有Bulk这样做。我已经看过我看到的其他帖子中提到的这个软件包 https:// github。 com / loresoft / EntityFramework.Extended
但它似乎专注于批量更新具有相同值的单个属性,或者我可以告诉。
关于我如何改进这一点的任何建议将是辉煌的。我还是相当新的c#,所以我仍然在寻找最好的办法。
我使用的是.net 4.5.2和实体框架6.1 .3以MSSQL 2014作为后端数据库
- 假设apiData中的类是相同的作为您的实体,您应该可以使用
Attach(newAccount,originalAccount)
来更新现有实体。 -
批量插入我使用
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 This works fine, however it just feels like this could be improved. 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 For bulk inserts I use 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屋!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();
}
Attach(newAccount, originalAccount)
to update an existing entity.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();