2013-07-24 24 views
10

我目前有一个有现有数据和新数据的模型。如何保存具有现有数据和新数据的模型?

作为一个例子,这是我的模型

public class NameDetails 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 

    } 

这是模拟数据,它目前拥有

List<NameDetails> Names = new List<NameDetails>{ 

       new NameDetails{Id = 1, Name = "Name 1"}, 
       new NameDetails{Id = 2 , Name = "Name 2"}, 
      }; 

现在假设我需要保存这个数据库上。我已经有在表中的id = 1,所以应该是一个更新,因为id = 2应该是一个添加...我该怎么做?

以前,当我写了节约使用资源库我没有任何添加或编辑 添加像这样,

context.NameDetails.Add(NameDetails); 
    context.SaveChanges(); 

或 编辑像这样,

var recordToUpdate = context.NameDetails.FirstOrDefault(x => x.Id== 1); 
recordToUpdate.Name = "New name"; 
context.SaveChanges(); 

这是否意味着我必须循环查看我的列表,并计算出什么是新的,哪些不是。还是有其他方法?

+1

您只有2个选项: - 查询数据库以确定对象是否已经存在。或者 - 让对象拥有一些属性以确定它是否是新的(例如,Id = 0) – Reda

+2

不确定它是否真正相关,但您从哪里获取新记录的Id值2? –

+0

@ user2266486或者制作一个执行upsert的存储过程,但我想知道这个问题没有更多 –

回答

0

试试这个:

var nameIds = Names.Select(n => n.Id); 

var recordsToUpdate = context.NameDetails.Where(x => nameIds.Contains(x.Id)); 
0

实体框架并没有在这些类型的情况下表现非常好。这应该让你接近你所寻找:

public class NameDetails 
{ 
    public int Id {get;set;} 
    public string Name {get;set;} 
} 

List<NameDetails> Names = new List<NameDetails> 
    { 
     new NameDetails{Id = 1, Name = "Name 1"}, 
     new NameDetails{Id = 2 , Name = "Name 2"}, 
    }; 


var toFetch = Names.Select(n => n.Id).ToArray(); 
var association = context.NameDetails 
         .Where(n => toFetch.Contains(n.Id)) 
         .ToDictionary(n => n.Id); 

foreach(var name in Names) 
{ 
    NameDetails existing; 
    if(association.TryGetValue(name.Id, out existing)) 
    { 
     // It exists, map the properties in name to existing 
    } 
    else 
    { 
     // It's new, perform some logic and add it to the context 
     context.NameDetails.Add(name); 
    } 
} 

context.SaveChanges() 

或者,你可以尝试劫持实体框架迁移的AddOrUpdate执行的UPSERT:

// You need a namespace import of System.Data.Entity.Migrations 
context.NameDetails.AddOrUpdate(names.ToArray()); 
context.SaveChanges(); 

我没有试过,但它应该可以工作,除非我在AddOrUpdate中有一个额外的逻辑。

+0

我简要介绍了AddOrUpdate的实现,尽管它构建表达式的方式是有点大脑弯曲 - 看起来不像是在创建任何神奇的upsert SQL。我很确定它会查询尝试获取您传入的实体,并在实体发现它时更新该实体,或者在没有此实体时添加它。当你播种一个数据库并且所有内容已经在内存中时,这很好,当你意外地向你的数据库发出一大堆TOP(1)查询时可能不那么好。 –

2

你可以使用一些适用于Entity Framework的约定。

举例来说,如果你的数据库上使用IDENTITY(1,1)(所以你插入的行自动生成的ID),你的实体属性应该使用StoreGeneratedPattern设定为Identity(型号第一种方法的情况下),以及您的Id财产与0值意味着它尚未添加到数据库

然后,您可以轻松决定要添加什么以及要更新什么。下面是一些伪(未经测试)代码:

foreach (var entity in entities) 
{ 
    if (entity.Id == 0) 
    { 
     // Adds to the context for a DB insert 
     context.Entities.Add(entity); 
    } 
    else 
    { 
     // Updates existing entity (property by property in this example, you could update 
     // all properties in a single shot if you want) 
     var dbEntity = context.Entities.Single(z => z.Id == entity.Id); 
     dbEntity.Prop1 = entity.Prop1; 
     // etc... 
    } 
} 

context.SaveChanges(); 
1

EF5 +只:

如果有一种方法来检测是否一个项目是新的(编号== 0是不错的,在ken2k的答案),你可以这样做是为了避免需要映射的事情:

foreach(var entity in entities) 
{ 
    context.NameDetails.Attach(entity); 
    context.Entry(entity).State = IsNewEntity(entity) 
            ? EntityState.Added 
            : EntityState.Modified; 
} 

这将告诉的EntityFramework为旧实体的新的实体,并更新创建插件。

相关问题