天天看點

Entity Framework Repository模式

Repository模式之前

如果我們用最原始的EF進行設計對每個實體類的“C(增加)、R(讀取)、U(修改)、D(删除)”這四個操作。

第一個:先來看看查詢,對于實體類簡單的查詢操作,每次都是這樣的過程會在代碼中擁有大量的重複 極為類似的代碼段。

using (var db = new EFContext("EFContext"))
            {
                var persons = db.Persons.Where(t => t.PersonName == "aehyok").OrderByDescending(t => t.PersonId).ToList();
                foreach (var p in persons)
                {
                    Console.WriteLine("The PersonName is {0} and Age {1}", p.PersonName, p.Age);
                }
            }
            Console.ReadLine();      

第二個:對于實體類的添加操作。

using (var db = new EFContext())
            {
                var stephen = new Person
                {
                     PersonName="aehyok0001",
                     Age=25,
                     Address="深圳南山",
                     Email="[email protected]"
                };
                db.Persons.Add(stephen);
                db.Persons.Attach(stephen);
                db.Entry(stephen).State = EntityState.Unchanged;  ////同上面db.Persons.Attach(stephen);作用是一樣的
                var jeffrey = new Person
                {
                    PersonName = "aehyok0002",
                    Age = 25,
                    Address = "深圳寶安",
                    Email = "[email protected]"
                };
                db.Entry(jeffrey).State = EntityState.Added;
                db.SaveChanges();
            }      

第三個:同理,删除操作如下。

using (var db = new EFContext())
            {
                var person = db.Persons.Where(m => m.PersonId == 4).FirstOrDefault();
                db.Persons.Remove(person);
                db.SaveChanges();
            }      

第四個:同理,修改操作如下。

using (var db = new EFContext())
            {
                var person = db.Persons.Where(m => m.PersonId == 4).FirstOrDefault();
                db.Persons.Remove(person);
                db.SaveChanges();
            }      

以上基于一個實體類簡單的CURD操作,當然對于查詢千變萬化。在資料通路層,我們可以專門的為每個類進行封裝業務處理類,但是其中類與類之間相同或類似的代碼段太多,對于編碼人員來說,更是浪費時間,同樣的代碼,要在項目的不同使用地方,進行多次的複制修改幾個代碼字段即可使用,那麼我們為什麼不進行簡單的封裝處理,來讓這一過程變得更加簡單,且使我們的代碼變得更為優雅,讓開發人員的維護操作更為簡單,也更易于擴充。基于以上考慮引出了我們的Repository設計模式。

Repository設計模式

 在《企業架構模式》中,譯者将Repository翻譯為資源庫。給出如下說明:通過用來通路領域對象的一個類似集合的接口,在領域與資料映射層之間進行協調。

那麼基于Rspository模式,資料通路層無非就是對資料進行增删改查,其中增、删、改等我們可以抽象出來寫一個公共的接口或抽象類來定義這些方法,并采用一個基類實作這些方法,這樣該基類派生的子類都會繼承增、删、改這些方法,這樣我們就避免了每個實體都要重複實作這些方法。一句話概括就是:通過接口 泛型 與ORM結合 實作了資料通路層更好的複用。

Repository代碼實作

 1.EF執行個體資料操作上下文對象

主要進行初始化資料庫,并進行設定自動更新資料庫

public class EFContext:DbContext
    {
        public EFContext() : base("default") 
        {
            Database.SetInitializer<EFContext>(new MigrateDatabaseToLatestVersion<EFContext,EFDbMigrationsConfiguration>());
        }
        public DbSet<Member> Members { get; set; }
        public DbSet<Score> Scores { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            modelBuilder.Entity<Member>().HasMany(b => b.Scores);
        }

    }

    internal sealed class EFDbMigrationsConfiguration : DbMigrationsConfiguration<EFContext>
    {
        public EFDbMigrationsConfiguration()
        {
            AutomaticMigrationsEnabled = true;//任何Model Class的修改將會自動直接更新DB
            AutomaticMigrationDataLossAllowed = true;  //可接受自動遷移期間的資料丢失的值
        }
    }      

2.BaseEntity類

BaseEntity類中定義了所有參加資料操作實體的公共屬性,是以我們把該類定義為抽象類,作為派生類的的基類。

public abstract class BaseEntity
    {
        [Key]
        public Guid Id { get; set; }

        public DateTime CreateDate { get; set; }

        public BaseEntity()
        {
            Id = Guid.NewGuid();
            CreateDate = DateTime.Now;
        }
    }      

3.Repository模式中最底層的接口實作IRepository

我們對實體的公共操作部分,提取為IRepository接口,比如常見的增加,删除、修改等方法。

public interface IRepository<TEntity> where TEntity:BaseEntity
    {
        DbSet<TEntity> Entities { get; }
        //增加單個實體
        int Insert(TEntity entity);
        //增加多個實體
        int Insert(IEnumerable<TEntity> entities);
        //更新實體
        int Update(TEntity entity);
        //删除
        int Delete(object id);
        //根據逐漸擷取實體
        TEntity GetByKey(object key);
    }      

其中的接口方法的定義,也會根據具體項目中業務,來進行定義适應自身的方法。具有一定的靈活性

我們發現接口的泛型TEntity有一個限制需要繼承BaseEntity,BaseEntity就是把實體中公共的屬性抽取出來,比如:Id(主鍵),CreateDate(建立時間)等。

4.Repository模式中基于接口的抽象類EFRepositoryBase

我們用一個抽象類EFRepositoryBase來實作接口中的方法,這樣派生的類都具有接口中定義的方法,也防止EFRepositoryBase直接被執行個體化。

public abstract class EFRepositoryBase<TEntity>:IRepository<TEntity> where TEntity:BaseEntity
    {
        EFContext EF = new EFContext();
        public DbSet<TEntity> Entities
        {
            get { return EF.Set<TEntity>(); }
        }

        public int Insert(TEntity entity)
        {
            Entities.Add(entity);
            return EF.SaveChanges();
        }

        public int Insert(IEnumerable<TEntity> entities)
        {
            Entities.AddRange(entities);
            return EF.SaveChanges();
        }

        public int Update(TEntity entity)
        {
            EF.Entry(entity).State = EntityState.Modified;
            return EF.SaveChanges();
        }

        public int Delete(object id)
        {
            ///删除操作實作
            return 0;
        }

        public TEntity GetByKey(object key)
        {
            return Entities.Find(key);
        }
    }      

5.簡單調用

Entity Framework Repository模式

可以看到就這樣即可進行調用處理。

總結

Entity Framework Repository模式

 簡單的項目分層,這裡隻是簡單的處理分層,并沒有真正意義上的。僅供參考。

簡單測試項目下載下傳連結位址

Entity Framework 5.0基礎系列目錄