使用EF在通用存储库中更新失败

时间:2015-09-02 15:37:30

标签: entity-framework

我已根据此codeproject sample创建了我的通用存储库。 Update()方法无效(没有任何错误)。当我添加这行代码时:

this.context.Entry(entity).State = EntityState.Modified;

发生此错误:

  

附加“MySolution.DAL.Event”类型的实体失败,因为同一类型的另一个实体已具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图表,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。

我该怎么办?

我的所有代码都在这里:

上下文:

public abstract class BaseEntity
{
    public Int64 ID { get; set; }
    public DateTime AddedDate { get; set; }
    public DateTime ModifiedDate { get; set; }
    public string IP { get; set; }
}
public class MyContext:DbContext
{
    public MyContext()
        : base("MyConnectionString")
    {
        base.Configuration.LazyLoadingEnabled = false;
        base.Configuration.ProxyCreationEnabled = false;
        base.Configuration.ValidateOnSaveEnabled = false;
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

        var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
      .Where(type => !String.IsNullOrEmpty(type.Namespace))
      .Where(type => type.BaseType != null && type.BaseType.IsGenericType
           && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }
        base.OnModelCreating(modelBuilder);

    }

    public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
   {
       return base.Set<TEntity>();
   }

    //public DbSet<Event> Events { get; set; }

}

存储库:

public class Repository<T> where T : BaseEntity
{
    private readonly MyContext context;
    private IDbSet<T> entities;
    string errorMessage = string.Empty;


    public Repository(MyContext context)
    {
        this.context = context;
    }

    public T GetById(object id)
    {
        return this.Entities.Find(id);
    }

    public T Insert(T entity)
    {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            var savedEntity=  this.Entities.Add(entity);
            this.context.SaveChanges();
            return savedEntity;
        }
        catch (DbEntityValidationException dbEx)
        {

            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    errorMessage += string.Format("Property: {0} Error: {1}",
                    validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;
                }
            }
            throw new Exception(errorMessage, dbEx);
        }
    }

    public void Update(T entity)
    {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }


            //this.context.Entry(entity).State = EntityState.Modified;not worked
            //this.context.Entry(entity).CurrentValues.SetValues(entity);not worked
            this.context.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    errorMessage += Environment.NewLine + string.Format("Property: {0} Error: {1}",
                    validationError.PropertyName, validationError.ErrorMessage);
                }
            }

            throw new Exception(errorMessage, dbEx);
        }
    }

    public void Delete(T entity)
    {
        try
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            this.Entities.Remove(entity);
            this.context.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {

            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    errorMessage += Environment.NewLine + string.Format("Property: {0} Error: {1}",
                    validationError.PropertyName, validationError.ErrorMessage);
                }
            }
            throw new Exception(errorMessage, dbEx);
        }
    }

    public virtual IQueryable<T> Table
    {
        get
        {
            return this.Entities;
        }
    }

    private IDbSet<T> Entities
    {
        get
        {
            if (entities == null)
            {
                entities = context.Set<T>();
            }
            return entities;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

您可以使用

this.context.Entry(entity).State = EntityState.Modified

然后 更新实体时,可以使用

public void Edit(Post post)
{ 
   var postInDb=DBReadWrite<Post>().GetById(post.ID);
   postInDb.ModifiedProp=post.ModifiedProp;
   DBReadWrite<Post>().Update(postInDb);
}

如果您不希望这样做,则可以使用ReflectionType来,您可以在存储库中捕获keyattribute并在db中找到实体并进行修改。

您的代码不起作用,因为EF认为您添加了一个实体,并且说我有相同的实体