【问题标题】:Many to many relationship update: Cannot insert duplicate key多对多关系更新:无法插入重复键
【发布时间】:2012-12-18 03:57:08
【问题描述】:

我还是EF代码新手,请多多包涵。

我有这些实体类:

    public class User
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string EmailAddress { get; set; }
        public string Password { get; set; }
        public virtual ICollection<Task> Tasks { get; set; }
        public virtual ICollection<Task> TaskAssignees { get; set; }

        public User()
        {
           Tasks = new List<Task>();
        }
    }

    public class Task
    {
       public int TaskId { get; set; }
       public string Name { get; set; }
       public virtual User CreateBy { get; set; }
       public int UserId { get; set; }
       public virtual ICollection<User> Assignees { get; set; }

       public Task()
       {
         Assignees = new List<User>();
       }
    }

带映射配置:

public class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        Property(u=>u.UserName)
            .IsRequired()
            .HasMaxLength(30);
        Property(u => u.EmailAddress)
            .IsRequired()
            .HasMaxLength(255);
        Property(u => u.Password)
            .IsRequired()
            .HasMaxLength(255);
    }
}

public class TaskMap : EntityTypeConfiguration<Domain.Entities.Task>
{
    public TaskMap()
    {
        Property(t => t.Name)
           .IsRequired()
           .HasMaxLength(255);
        HasRequired(t => t.CreateBy)
            .WithMany(u => u.Tasks)
            .HasForeignKey(t => t.UserId)
            .WillCascadeOnDelete(false)
            ;
        HasMany(t => t.Assignees)
            .WithMany(u => u.TaskAssignees)
            .Map(a =>
                {
                    a.ToTable("TaskAssignees");
                    a.MapLeftKey("TaskId");
                    a.MapRightKey("UserId");
                })
            ;
    }
}

还有一个相当通用的存储库类:

    public class EntityRepository<TEntity> : IEntityRepositoryGetWithCRUD<TEntity> where TEntity : class 
    {
        internal DbContext context;
        internal DbSet<TEntity> dbSet;

        public EntityRepository(DbContext Context)
        {
            this.context = Context;
            this.dbSet = context.Set<TEntity>();
        }

        public virtual IQueryable<TEntity> All
        {
            get { return dbSet; }
        }

        public virtual IQueryable<TEntity> AllIncluding(params System.Linq.Expressions.Expression<Func<TEntity, object>>[] IncludeProperties)
        {
            IQueryable<TEntity> query = dbSet;

            foreach (var includeProperty in IncludeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query;
        }

        public virtual IEnumerable<TEntity> Get(
            Expression<Func<TEntity, bool>> Filter = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> OrderBy = null,
            params System.Linq.Expressions.Expression<Func<TEntity, object>>[] IncludeProperties)
        {
            IQueryable<TEntity> query = dbSet;

            if (Filter != null)
            {
                query = query.Where(Filter);
            }

            foreach (var includeProperty in IncludeProperties)
            {
                query = query.Include(includeProperty);
            }

            if (OrderBy != null)
            {
                return OrderBy(query).ToList();
            }
            else
            {
                return query.ToList();
            }
        }

        public virtual TEntity Find(int Id)
        {
            return dbSet.Find(Id);
        }

        public virtual void Insert(TEntity Entity)
        {
            dbSet.Add(Entity);
        }

        public virtual void Update(TEntity Entity)
        {
            dbSet.Add(Entity);
            context.Entry(Entity).State = EntityState.Modified;
        }

        public virtual void Delete(int Id)
        {
            var entity = dbSet.Find(Id);
            dbSet.Remove(entity);
        }

        public virtual void Delete(TEntity Entity)
        {
            if (context.Entry(Entity).State == EntityState.Detached)
            {
                dbSet.Attach(Entity);
            }
            dbSet.Remove(Entity);

        }

        public virtual void Dispose()
        {
            context.Dispose();
        }

        public virtual void Save()
        {
            context.SaveChanges();
        }

    }

通过上面的代码,我可以顺利地将一个新的任务行插入到 db 中。 然而,当我尝试用这个简单的代码更新任务时,问题就出现了:

 Task task = repository.Find(2);

 if (task != null)
 {
    task.Name = "Test Update";
    repository.Update(task);
    repository.Save();
 }

错误说:

违反主键约束“PK_dbo.TaskAssignees”。不能 在对象“dbo.TaskAssignees”中插入重复键。该声明有 被终止了。

谁能给我一些启示?

【问题讨论】:

    标签: c# ef-code-first many-to-many primary-key entity-framework-5


    【解决方案1】:

    我认为您的问题可能在于您如何调用更新。

    我不确定,但我认为您的实体已经由上下文管理,因此您不需要添加它以使其处于更新状态。如果您只是删除更新调用并尝试保存,是否一切正常?

    【讨论】:

    • 谢谢,这解决了我的问题...我按照一些教程来创建通用存储库类,我想我没有很好地遵循它。
    • 我的猜测是更新是将任务添加为新对象,并在您持久保存相关受让人时尝试将其重新保存为新实体。不过,我在这里扩展了我的知识。
    猜你喜欢
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 1970-01-01
    • 2020-07-22
    • 2021-08-24
    • 1970-01-01
    相关资源
    最近更新 更多