gpt4 book ai didi

c# - Entity Framework 批量插入/更新关系

转载 作者:搜寻专家 更新时间:2023-10-30 23:35:29 25 4
gpt4 key购买 nike

我有一个场景,我需要对大量数据执行数据库更新。有一些外键关系需要同时添加,我得到了一个外来对象列表,所以我不必每次都访问数据库来检查它们是否存在/添加它们等:

using(DbEntities db = new DbEntities())
{
// Get list of all books so don't have to hit every time
Dictionary<int, Book> books = db.Books.ToDictionary(k => k.BookId, v => v);

// Loop through big file to import each row
foreach(var item in bigFile)
{
Person person = new Person { FirstName = item.FirstName, LastName = item.LastName };

foreach(var book in item.Books)
{
if(!books.ContainsKey(book.BookId))
{
// Add book to DB if doesn't exist
Book bookToAdd = new Book { BookId = book.BookId, Name = book.Name };
db.Books.Add(bookToAdd);

books.Add(bookToAdd.BookId, bookToAdd);
}

person.Books.Add(books[book.BookId]);
}

db.People.Add(person);
}

db.SaveChanges();
}

此解决方案的问题是导入开始时很快,然后随着它的进行而减慢,变得非常慢。这似乎是由于上下文因更改跟踪而变得臃肿。

我看到帖子建议使用 db.Configuration.AutoDetectChangesEnabled = false 但是当我这样做时,关系不会被添加。我可以通过强制 DetectChanges() 来完成这项工作,但这似乎违背了目的,因为我必须在循环的每次迭代中都这样做。

因此,我将 DB 上下文移动到循环中,以便每次都重新创建它。这样做意味着我不能再拥有分离的书籍列表,所以我必须为每一行对数据库进行 .Any().Single() 调用(我不知道这是否是一个主要的性能问题,但总是尽量不频繁地访问数据库):

// Loop through big file to import each row
foreach(var item in bigFile)
{
// Create DB context each time
using(DbEntities db = new DbEntities())
{
Person person = new Person { FirstName = item.FirstName, LastName = item.LastName };

foreach(var book in item.Books)
{
if(!db.Books.Any(m => m.BookId = bookId))
{
// Add book to DB if doesn't exist
Book bookToAdd = new Book { BookId = bookId, Name = book.Name

db.Books.Add(bookToAdd);
}

person.Books.Add(db.Books.Single(m => m.BookId = bookId));
}

db.People.Add(person);

db.SaveChanges();
}
}

这大大加快了它的速度,但在大约 5,000-10,000 行之后它仍然开始变慢,我想知道我的选择是什么? ...除了使用存储过程来完成这一切!

最佳答案

IMO 这两种解决方案都不好。第一个是在内存(和数据库上下文)中加载整个现有的 Books 表,第二个对每本书执行 2 个数据库查询 - 一个使用 Any ,另一个使用 单例

由于我的测试没有显示上下文更改跟踪的性能问题,我将使用第一种方法的变体和第二种方法的元素。我不会加载整个 Books 表,而是使用按需填充的本地字典,对每个新书 ID 进行单个数据库查询:

using (DbEntities db = new DbEntities())
{
// The local book dictionary
Dictionary<int, Book> books = new Dictionary<int, Book>();

// Loop through big file to import each row
foreach (var item in bigFile)
{
Person person = new Person { FirstName = item.FirstName, LastName = item.LastName };

foreach (var itemBook in item.Books)
{
Book book;

// Try get from local dictionary
if (!books.TryGetValue(itemBook.BookId, out book))
{
// Try get from db
book = db.Books.FirstOrDefault(e => e.BookId == itemBook.BookId);
if (book == null)
{
// Add book to DB if doesn't exist
book = new Book { BookId = itemBook.BookId, Name = itemBook.Name };
db.Books.Add(book);
}
// add to local dictionary
books.Add(book.BookId, book);
}

person.Books.Add(book);
}

db.People.Add(person);
}

db.SaveChanges();
}

关于c# - Entity Framework 批量插入/更新关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43252161/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com