entity framework添加如果没有更新则不存在

我喜欢AddOrUpdate允许您指定要检查的filter以避免添加重复项的事实。 但我想要没有更新的类似function。

现在我做这样的事情:

var checkProfile = from p in db.Profile where p => p.LastName == newProfile.lastName && p => p.FirstName == newProfile.firstName && p => p.Middle== newProfile.middle select p; if (checkProfile.FirstOrDefault() == null) { db.Profile.Add(newProfile); db.SaveChanges(); } 

我知道我可以这样做:

 db.Profile.AddOrUpdate(p => new {p.LastName, p.FirstName, p.Middle}, newProfile); db.SaveChanges(); 

但我宁愿在这种情况下跳过修改数据。

第一个例子做了我想要的,但有更多的代码。 在第一个例子中是否有更简单/更清洁的方式来做我想要的事情?

更新:

我喜欢Ognyan Dimitrov的建议。 我正在尝试实现它。 我的模型inheritance自BaseEntity。 我可以在那里放一个通用版本吗?

我的模型定义如下:

 public class Address :BaseEntity { 

我的BaseEntity:

 public class BaseEntity { public virtual T AddIfNotExists(T entity, Expression<Func> predicate = null) { var exists = predicate != null ? DbSet.Any(predicate) : DbSet.Any(); return !exists ? DbSet.Add(entity) : null; } } 

我收到Any(…)和Add(…)的错误。 Add(…)的错误是’非静态字段,方法或属性’System.Data.Entity.DbSet.Add(object)”需要对象引用

我应该使用这个。添加(对象)?

更新2:

我创建了这段代码:

 public static class DbSetExtensions { public static T AddIfNotExists(this DbSet dbSet, T entity, Expression<Func> predicate = null) where T : class, new() { var exists = predicate != null ? dbSet.Any(predicate) : dbSet.Any(); return !exists ? dbSet.Add(entity) : null; } } 

现在我试着像这样称呼它,但这不正确。 原谅我缺乏理解。

 _db.ProfileIdentifier.AddIfNotExists(newIdentifier, pi => new {pi.ProfileId, pi.ProfileIdentifierTypeId, pi.ProfileIdentifierValue}); 

更新 – 解决方案:

我可以像这样调用DbSetextensions:

 _db.ProfileIdentifier.AddIfNotExists(newIdentifier, pi => pi.ProfileId == profileId && pi.ProfileIdentifierTypeId == (int)type && pi.ProfileIdentifierValue == value); 

非常感谢与我合作Ognyan!

您是否尝试检查实体是否存在,如果不存在 – 添加它? 像这样 :

UPDATE

 using System.Linq.Expressions; public class ContextWithExtensionExample { public void DoSomeContextWork(DbContext context) { var uni = new Unicorn(); context.Set().AddIfNotExists(uni , x => x.Name == "James"); } } public static class DbSetExtensions { public static T AddIfNotExists(this DbSet dbSet, T entity, Expression> predicate = null) where T : class, new() { var exists = predicate != null ? dbSet.Any(predicate) : dbSet.Any(); return !exists ? dbSet.Add(entity) : null; } } 

您可以直接使用此方法,并记住在调用后调用DbContext.SaveChanges()。

我用了类似的东西,阅读这两篇post来制作我的代码。 我希望帮助那些需要与AddOrUpdate类似签名的人。

entity framework添加如果没有更新则不存在

使AddOrUpdate仅更改某些属性

 using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace System.Data.Entity.Migrations { // // Summary: // Metodos de extensão para System.Data.Entity.IDbSet public static class DbSetMigrationsGustavoExtensions { ///  /// Adiciona uma entidade se ela não existe ainda /// Assinatura semelhante ao AddOrUpdate ///  ///  /// Set onde serão adicionadas as entidades /// Campos usados na comparação /// Entidades para adicionar public static void AddIfNotExists(this IDbSet set, Expression> identifierExpression, params TEntity[] entities) where TEntity : class { var identifyingProperties = GetProperties(identifierExpression).ToList(); var parameter = Expression.Parameter(typeof(TEntity)); foreach (var entity in entities) { var matches = identifyingProperties.Select(pi => Expression.Equal(Expression.Property(parameter, pi.Name), Expression.Constant(pi.GetValue(entity, null)))); var matchExpression = matches.Aggregate(null, (agg, v) => (agg == null) ? v : Expression.AndAlso(agg, v)); var predicate = Expression.Lambda>(matchExpression, new[] { parameter }); if (!set.Any(predicate)) { set.Add(entity); } } } private static IEnumerable GetProperties(Expression> exp) where T : class { Debug.Assert(exp != null); Debug.Assert(exp.Body != null); Debug.Assert(exp.Parameters.Count == 1); var type = typeof(T); var properties = new List(); if (exp.Body.NodeType == ExpressionType.MemberAccess) { var memExp = exp.Body as MemberExpression; if (memExp != null && memExp.Member != null) properties.Add(type.GetProperty(memExp.Member.Name)); } else if (exp.Body.NodeType == ExpressionType.Convert) { var unaryExp = exp.Body as UnaryExpression; if (unaryExp != null) { var propExp = unaryExp.Operand as MemberExpression; if (propExp != null && propExp.Member != null) properties.Add(type.GetProperty(propExp.Member.Name)); } } else if (exp.Body.NodeType == ExpressionType.New) { var newExp = exp.Body as NewExpression; if (newExp != null) properties.AddRange(newExp.Members.Select(x => type.GetProperty(x.Name))); } return properties.OfType(); } ///  /// Faz um set.Any(predicate) /// Se não existe nada no set então adiciona ///  ///  /// Set onde será adicionada a entidade /// Condição (exemplo: dbUser => dbUser.Nome == "Gustavo") /// Entidade para adicionar ///  public static T AddIfNotExists(this IDbSet set, Expression> predicate, T entity) where T : class, new() { return !set.Any(predicate) ? set.Add(entity) : null; } } } 

引用自MSDN EF文章 。

插入或更新模式

某些应用程序的常见模式是将实体添加为新实体(导致数据库插入)或将实体附加为现有实体,并根据主键的值将其标记为已修改(导致数据库更新)。 例如,当使用数据库生成的整数主键时,通常将零键作为新实体和具有非零键的实体视为现有实体。 可以通过基于主键值的检查来设置实体状态来实现该模式。

请注意,当您将状态更改为Modified时,实体的所有属性都将标记为已修改,并且在调用SaveChanges时,所有属性值都将发送到数据库。

 context.Entry(blog).State = blog.BlogId == 0 ? EntityState.Added : EntityState.Modified; context.SaveChanges(); 

解决方案是可以的,当你必须只添加一个项目时,如果你必须添加多个项目,它在性能方面非常昂贵。 我认为有一个更好的解决方案:

 public static class DbSetExtensions { public static EntityEntry AddIfNotExists(this DbSet dbSet, TEnt entity, Func predicate) where TEnt : class { var exists = dbSet.Any(c => predicate(entity).Equals(predicate(c))); return exists ? null : dbSet.Add(entity); } public static void AddRangeIfNotExists(this DbSet dbSet, IEnumerable entities, Func predicate) where TEnt : class { var entitiesExist = from ent in dbSet where entities.Any(add => predicate(ent).Equals(predicate(add))) select ent; dbSet.AddRange(entities.Except(entitiesExist)); } } 

所以稍后它可以像这样使用:

 using (var context = new MyDbContext()) { var user1 = new User { Name = "Peter", Age = 32 }; context.Users.AddIfNotExists(user1, u => u.Name); var user2 = new User { Name = "Joe", Age = 25 }; context.Users.AddIfNotExists(user2, u => u.Age); // Adds user1 if there is no user with name "Peter" // Adds user2 if there is no user with age 25 context.SaveChanges(); } 

我唯一想到的是使用IEqualityComparer ,但这并没有真正停止工作,只是抽象它并创建更清晰的代码。

对我有用的是:

 public static void AddIfNotExists(this DbSet dbSet, Func predicate, params T [] entities) where T : class, new() { foreach (var entity in entities) { var newValues = predicate.Invoke(entity); Expression> compare = arg => predicate(arg).Equals(newValues); var compiled = compare.Compile(); var existing = dbSet.FirstOrDefault(compiled); if (existing == null) { dbSet.Add(entity); } } }