通过实体框架保存一个明确的实体 [英] Saving an explicit entity through Entity Framework

查看:107
本文介绍了通过实体框架保存一个明确的实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我正在从Excel文件读取数据,我需要使用EF保存。阅读excel之后,我在EF模型中构造一个类型的实体 - 假设。



有可能这个特殊的假期已经存在于我的数据库中,也可能没有。我只能通过阅读Excel文件来知道它。所以,我检查该实体是否存在,如果是,我必须修改现有的实体或添加一个新的实体。



以下是我如何处理逻辑。

  foreach (clientDataObj.Holidays中的var holiday)
{
//检查现有假期,无需考虑位置,因为所有假期都将存在于根级别。
假现代HOLiday =
ClientContext.Holidays.SingleOrDefault(h => string.Equals(h.Date,holiday.Date));

if(existingHoliday == null)
{
rootLocation.Holidays.Add(holiday);
}
else
{
holiday.HolidayId = existingHoliday.HolidayId;
ClientContext.Entry(existingHoliday).State = System.Data.Entity.EntityState.Detached;
ClientContext.Entry(holiday).State = System.Data.Entity.EntityState.Modified;
}
}

ClientContext.SaveChanges();

我还没有运行代码看看它是否正常工作。有人可以想出这是否是这样做,还是解决这个问题的其他最佳做法。

解决方案

p>不,那不行。分离实体不会删除它,它只是从上下文的跟踪中分离。



您需要删除它并添加新实体:

  ClientContext.Entry(existingHoliday).State = EntityState.Deleted; 
ClientContext.Entry(holiday).State = EntityState.Added;

此外,如果Excel文件中有两个相同的假期,您可以通过一个你已经添加了,所以你需要检查。因为您尚未调用 SaveChanges ,所以该实体不在数据库中:

  if(ClientContext.Entry(existingHoliday).State == EntityState.Added)
ClientContext.Entry(existingHoliday).State == EntityState.Detached;

我不知道为什么要将它们添加到 rootLocation 当它们不存在于数据库中时,如果我遵循你的逻辑,你应该将它们添加到上下文中,所以你可能有这个循环:

  foreach(clientDataObj.Holidays中的var holiday)
{
假期existingHoliday =
ClientContext.Holidays.SingleOrDefault(h => string.Equals(h日期,假日日期));
if(existingHoliday!= null)
{
holiday.Id = existingHoliday.Id;
ClientContext.Entry(existingHoliday).State =
ClientContext.Entry(existingHoliday).State == EntityState.Added
? EntityState.Detached
:EntityState.Deleted;
}
ClientContext.Entry(holiday).State = System.Data.Entity.EntityState.Added;
}

再次,我不知道什么 rootLocation 是你的逻辑可能不同。



作为进一步的优化,如果假日列表不是太大,你应该将其全部加载到内存,而不是在每次迭代中调用 SingleOrDefault ,这将打到数据库。



所以只有一个命中数据库加载它们(再次,如果没有太多的内存不是关心),并在客户端搜索:

  var allHolidays = ClientContext.Holidays.ToList(); 
foreach(clientDataObj.Holidays中的var holiday)
{
假期existingHoliday =
allHolidays.SingleOrDefault(h => string.Equals(h.Date,holiday.Date)) ;
/ * ... * /
}

数据库一次查询



请注意,如果同时使用此方法和上述方法,您还需要将新的假期添加到列表中,以便它们被检查,如果excel导入可能有重复。这一切都在您的问题上未提出,因此请检查规格。


Let's say I'm reading data from an Excel file and I need to save this using EF. After reading excel, I construct an entity of type in my EF model - say Holiday.

Chance is that this particular holiday already exist in my DB or may not. I can't know it just by reading the Excel file. So, I check whether that entity exist, if so I have to modify the existing entity or add a new entity.

Following is how I'm handling the logic.

 foreach (var holiday in clientDataObj.Holidays)
 {
     // to check for existing holidays, no need to consider the location, as all holidays will anyway exist at root level.
     Holiday existingHoliday =
                ClientContext.Holidays.SingleOrDefault(h => string.Equals(h.Date, holiday.Date));

     if (existingHoliday == null)
     {
         rootLocation.Holidays.Add(holiday);
     }
     else
     {
         holiday.HolidayId = existingHoliday.HolidayId;
         ClientContext.Entry(existingHoliday).State = System.Data.Entity.EntityState.Detached;
         ClientContext.Entry(holiday).State = System.Data.Entity.EntityState.Modified;
     }
}

ClientContext.SaveChanges();

I haven't yet run the code to see if it's working. Can someone give an idea of whether this is the way to do it, or is there any other best practice in addressing this problem.

解决方案

No, that won't work. Detaching an entity doesn't remove it, it just detaches from the context's tracking.

You need to remove it and add the new one:

ClientContext.Entry(existingHoliday).State = EntityState.Deleted;
ClientContext.Entry(holiday).State = EntityState.Added;

Also, in the event that there are two same holidays in the excel file, you may pass through one that you already added, so you need to check for that. Detaching here will work because you haven't called SaveChanges yet so the entity is not in the database yet:

if(ClientContext.Entry(existingHoliday).State == EntityState.Added)
   ClientContext.Entry(existingHoliday).State == EntityState.Detached;

I'm not sure about why you are adding them to rootLocation when they don't exist on the database, you should be adding them to the context if I follow your logic, so you may have this loop:

foreach (var holiday in clientDataObj.Holidays)
{
   Holiday existingHoliday =
                ClientContext.Holidays.SingleOrDefault(h => string.Equals(h.Date, holiday.Date));  
   if (existingHoliday != null)
   {
      holiday.Id = existingHoliday.Id;
      ClientContext.Entry(existingHoliday).State = 
                    ClientContext.Entry(existingHoliday).State == EntityState.Added       
                             ? EntityState.Detached 
                             : EntityState.Deleted;
   }       
   ClientContext.Entry(holiday).State = System.Data.Entity.EntityState.Added;
}

Again, I'm not sure what rootLocation is so your logic might be different.

As a further optimization, if the holiday list is not too big, you should load it all on memory, instead of calling SingleOrDefault on every iteration, which will hit the database.

So have just a single hit to the database loading all of them (again, if there are not too many and memory is not a concern), and search in the client:

var allHolidays = ClientContext.Holidays.ToList();    
foreach (var holiday in clientDataObj.Holidays)
{
   Holiday existingHoliday =
                allHolidays.SingleOrDefault(h => string.Equals(h.Date, holiday.Date));
   /* ... */
}

This should only hit the database once for querying

Note that if using both this method and the above, you'll need to add the new holidays to the list too, so that they get checked against, if the excel import may have duplicates. This is all unspecced in your question so check the specs.

这篇关于通过实体框架保存一个明确的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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