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

那么这是否意味着我必须遍历我的列表并找出什么是新的,什么不是……或者还有其他方法吗?

4

4 回答 4

2

您可以使用一些适用于实体框架的约定。

例如,如果您IDENTITY(1,1)在数据库上使用(因此它会自动为您插入的行生成 ID),您的实体属性应该使用StoreGeneratedPatternset as 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();
于 2013-07-24T12:50:47.387 回答
1

仅 EF5+:

如果您有办法检测一个项目是否是新的(Id == 0 很好,如 ken2k 的回答),您可以这样做以避免需要映射事物:

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

这将告诉 EntityFramework 为新实体创建 INSERT,为旧实体创建 UPDATE。

于 2013-07-24T22:00:27.693 回答
0

尝试这个:

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

var recordsToUpdate = context.NameDetails.Where(x => nameIds.Contains(x.Id));
于 2013-07-24T12:34:52.717 回答
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

于 2013-07-24T12:42:47.020 回答