c# – EF应该封装在基类中吗?

我是EF的新手,但我已经编程了21年.我喜欢干燥和通用的东西,但我刚才做的事情似乎错了,但我不能指责它.

EF上见过的每个例子都有开发人员为每个POCO类创建4个单独的CRUD方法.所以我打算不必这样做,这就是我提出的:

模型:

  public class Model1 : DbContext
  {
    public Model1()
        : base("name=Model1")
    {
    }

     public virtual DbSet<Member> Members { get; set; }
  }

所有业务层的基类:

using System.Data.Entity;
using System.Reflection;

namespace biz
{
  public abstract class EFObject<T> where T : EFObject<T>
  {
    public int Id { get; set; }

    internal static readonly string DbSetProperyName = typeof(T).Name + "s";

    public static EFCollection<T> Collection
    {
      get
      {
        using (var db = new Model1())
        {
          PropertyInfo p = db.GetType().GetProperty(DbSetProperyName);
          DbSet<T> collection = (DbSet<T>)p.GetValue(db);
          return new EFCollection<T>(collection);
        }
      }
    }

    public void Insert()
    {
      using (var db = new Model1())
      {
        PropertyInfo p = db.GetType().GetProperty(DbSetProperyName);
        DbSet<T> collection = (DbSet<T>)p.GetValue(db);
        collection.Add((T)this);
        db.SaveChanges();
      }
    }

    public void Save()
    {
      if (Id == 0)
        Insert();
      else
        Update();
    }

    public void Update()
    {
      using (var db = new Model1())
      {
        PropertyInfo p = db.GetType().GetProperty(DbSetProperyName);
        DbSet<T> collection = (DbSet<T>)p.GetValue(db);
        T dbItem = collection.Find(Id);
        foreach (PropertyInfo pi in typeof(T).GetProperties())
        {
          pi.SetValue(dbItem, pi.GetValue(this));
        }
        db.SaveChanges();
      }
    }
  }
}

通用集合类:

using System.Collections.Generic;

namespace biz
{
  public class EFCollection<T> : List<T> where T : EFObject<T>
  {
    public EFCollection()
    {
    }

    public EFCollection(IEnumerable<T> collection)
    {
      AddRange(collection);
    }

    public void Save()
    {
      foreach (T item in this)
        item.Save();
    }
  }
}

示例中间层类:

namespace biz
{
  public class Member : EFObject<Member>
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Client[] Clients;
    public Good[] Goods;
    public decimal Percentage;
  }
}

用法:

  var member = new biz.Member() { FirstName = "Brad", LastName = "Pitt", Percentage = 1 };//
  member.Save();
  member = biz.Member.Collection.Find(o=>o.Id == member.Id);
  member.FirstName = "Cherry";
  member.Save();

使用代码有效,但我想知道这种方法会让我遇到什么样的问题?

有一件事让我误解了我所做的事情,也许是因为我现在对EF了解得足够好.在我的更新场景中,我1)使用一个会话从集合中获取对象,2)断开连接,3)更新对象的属性,3)开始新的会话,3)通过主键从中找到匹配的对象db(它不再是同一个对象!),4)通过反射更新它,然后5)保存更改.所以有两个对象涉及的不是一个和反射.我想我必须“放开”连接以保持原始对象一旦得到它,我不知道如何解决这个问题.

最佳答案 这是一种常见的反模式(出于多种原因).

EF已经实现了UoW和存储库模式,因此,实质上,您正在创建抽象抽象.

请参阅以下文章,了解为什么这是坏事:

> http://www.ben-morris.com/why-the-generic-repository-is-just-a-lazy-anti-pattern/
> Why is a generic repository considered an anti-pattern?
> http://www.planetgeek.ch/2012/05/05/what-is-that-all-about-the-repository-anti-pattern/
> https://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/
> https://lostechies.com/jimmybogard/2012/09/20/limiting-your-abstractions/
> http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/

点赞