问题
I am still new in EF code first, so please be lenient with me.
I have these entity classes:
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>();
}
}
with mapping configuration:
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");
})
;
}
}
and a fairly generic repository class:
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();
}
}
With the above codes, i can insert a new task row into db smoothly. However the problem arise when i tried to update the task with this simple code:
Task task = repository.Find(2);
if (task != null)
{
task.Name = "Test Update";
repository.Update(task);
repository.Save();
}
The error said:
Violation of PRIMARY KEY constraint 'PK_dbo.TaskAssignees'. Cannot insert duplicate key in object 'dbo.TaskAssignees'. The statement has been terminated.
Could anybody give me some enlightenment please?
回答1:
I think your problem might be in how you are calling update.
I am not certain but I think your entity is already being managed by the context, so you should not need to add it to put it in an updated state. Does everything work if you just remove the call to update and try to save?
来源:https://stackoverflow.com/questions/13926020/many-to-many-relationship-update-cannot-insert-duplicate-key