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="aehyok@163.com"
                };
                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 = "Leo@163.com"
                };
                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 5.0基礎系列目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM