EntityFramework存储库模式

时间:2016-03-14 16:39:05

标签: c# asp.net entity-framework

我的代码一直存在问题。我已经开始学习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类。

1 个答案:

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