EntityFramework仓储模式

4

我在编程过程中遇到了一个问题。我开始学习Entityframework,参考了微软虚拟学院网站上的资料,他们有一份关于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类。

您是否有重复的主键值? - jrummell
你需要检查数据库是否生成了主键列作为标识。如果YourEntity有一个名为YourEntityID的整数属性,那么使用Code First通常会自动发生这种情况。所以在你的情况下,UsersExtended是否有UsersExtendedID作为关键字,或者它的名称是其他什么?如果它被命名为其他内容,那么在数据库中是否将其标记为标识列? - user964769
1个回答

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扩展方法,以仅加载所需实体。


谢谢,我现在意识到我的ToList()调用创建了新的断开连接的实体,它们具有相同的PK但未附加到上下文。 - Milos Zivkovic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接