我的代码一直存在问题。我已经开始学习Entityframework,作为我使用过Microsoft Virtual Academy网站的资源,他们有一个简短的Entity Framework简介和asp.net。他们创建了这个采用poco类的存储库泛型类。
public class Repository<T> where T : class
{
private BlogDataContext context = null;
protected DbSet<T> DbSet { get; set; }
public Repository()
{
this.context = new BlogDataContext();
DbSet = context.Set<T>();
}
public List<T> getAll()
{
return DbSet.ToList();
}
public T Get(int id)
{
return DbSet.Find(id);
}
public void Add(T entity)
{
DbSet.Add(entity);
}
public void Update(T entity)
{
context.Entry<T>(entity).State = EntityState.Modified;
}
public void Delete(int id)
{
DbSet.Remove(DbSet.Find(id));
}
public void SaveChanges()
{
context.SaveChanges();
}
}
当您需要使用ASP.NET控件编辑数据库中的数据时出现问题,到目前为止,我已手动将数据绑定到控件并通过使用Get(int Id)
查找数据然后更新来更新。最近我发现可以使用ObjectDataSource控件自动执行该过程,但更新方法会抛出错误
附加“CarDealership.DataLayer.UsersExtended”类型的实体 失败,因为同一类型的另一个实体已经相同 主键值。
UsersExtended
是一个poco类。
答案 0 :(得分:3)
不要使用Get
方法,因为它会将结果实体附加到您的上下文中,当您将断开连接的POCO实体传递给具有相同ID的Update
方法时,EF将会抛出那个例外。
如果您的实体继承自您定义所有实体的PK属性的公共类,例如:
public class Entity
{
public int Id{get;set;}
}
要避免该问题,您可以将以下方法添加到存储库,以检查数据库中是否存在该行:
public class Repository<T> where T : Entity
{
//...
public bool Exist(int id)
{
return DbSet.Exist(e=>e.Id==id);
}
}
如果您没有设计,可以在业务层执行以下操作以检查相同内容:
var repository= new Repository<UsersExtended>();
bool exist= repository.GetAll().Exist(e=>e.Id==id);
if(exist)
{
repository.Update(yourEntity)
}
另一个重要的事情是,永远不要从DbSet调用ToList
扩展方法,将所有表加载到内存中。把它改成这样的东西:
public IQueryable<T> GetAll()
{
return DbSet;
}
始终尝试在BL中查询您的数据,并在查询结束时调用ToList
扩展方法,仅加载所需的实体。