EF(六)--EF實體類的繼承

實體類的繼承

所有實體類都會有一些公共屬性,可以把這些屬性定義到一個父類中。比如:

public abstract class BaseEntity
{
    public long Id { get; set; } //主鍵
    public bool IsDeleted { get; set; } = false; //軟刪除
    public DateTime CreateDateTime { get; set; } = DateTime.Now;//創建時間
    public DateTime DeleteDateTime { get; set; } //刪除時間
}

使用公共父類的好處不僅是寫實體類簡單了,而且可以提供一個公共的Entity 操作類:

public abstract class BaseEntity
{
    public long Id { get; set; } //主鍵
    public bool IsDeleted { get; set; } = false; //軟刪除
    public DateTime CreateDateTime { get; set; } = DateTime.Now;//創建時間
    public DateTime DeleteDateTime { get; set; } //刪除時間
}

使用公共父類的好處不僅是寫實體類簡單了,而且可以提供一個公共的Entity 操作類:

class BaseDAO<T> where T:BaseEntity
{
    private MyDbContext ctx;//不自己維護MyDbContext 而是由調用者傳遞,因爲調用者可以要執行很多操作,由調用者決定什麼時候銷燬。
    public BaseDAO (MyDbContext ctx)
    {
        this.ctx = ctx;
    }
    public IQueryable<T> GetAll()//獲得所有數據(不要軟刪除的)
    {
        return ctx.Set<T>().Where(t=>t.IsDeleted==false);//這樣自動處理軟刪除,避免了忘了過濾軟刪除的數據
    }
    public IQueryable<T> GetAll(int start,int count) //分頁獲得所有數據(不要軟刪除的)
    {
        return GetAll().Skip(start).Take(count);
    }
    public long GetTotalCount()//獲取所有數據的條數
    {
        return GetAll().LongCount();
    }
    public T GetById(long id)//根據id 獲取
    {
        return GetAll().Where(t=>t.Id==id).SingleOrDefault();
    }
    public void MarkDeleted(long id)//軟刪除
    {
        T en = GetById(id);
        if(en!=null)
        {
            en.IsDeleted = true;
            en.DeleteDateTime = DateTime.Now;
            ctx.SaveChanges();
        }
    }
}

DAL同層內返回IQueryable比IEnumerable更好

下面的代碼會報錯:

using (MyDbContext ctx = new MyDbContext())
{
    BaseDAO<Student> dao = new BaseDAO<Student>(ctx);
    foreach(var s in dao.GetAll())
    {
        Console.WriteLine(s.Name);
        Console.WriteLine(s.Class.Name);
    }
}

原因是什麼?怎麼Include?需要using System.Data.Entity;

using (MyDbContext ctx = new MyDbContext())
{
    BaseDAO<Student> dao = new BaseDAO<Student>(ctx);
    foreach(var s in dao.GetAll().Include(t=>t.Class))
    {
        Console.WriteLine(s.Name);
        Console.WriteLine(s.Class.Name);
    }
}

有兩個版本的Include、AsNoTracking:

  1. DbQuery 中的:DbQuery AsNoTracking()、DbQuery Include(string path)
  2. QueryableExtensions 中的擴展方法: AsNoTracking(this IQueryable source) 、 Include(this IQueryable source, string path)、Include<T, TProperty>(this IQueryablesource, Expression<Func<T, TProperty>> path)

DbSet繼承自DbQuery;

Where()、Order、Skip()等這些方法返回的是IQueryable接口。

因此如果在IQueryable接口類型的對象上調用Include、AsNoTracking就要using System.Data.Entity

linq

簡介

查詢Id>1的狗有如下兩種寫法:

var r1 = dogs.Where(d => d.Id > 1);
var r2 = from d in dogs where d.Id>1 select d;

第一種寫法是使用lambda 的方式寫的,官方沒有正式的叫法,我們就叫“lambda寫法”;

第二種是使用一種叫Linq(讀作:link)的寫法,是微軟發明的一種類似SQL的語法,給我們一個新選擇。兩種方法是可以互相替代的,沒有哪個好、哪個壞,看個人習慣。

我的經驗:需要join等複雜用法的時候Linq更易懂,一般的時候“lambda寫法”更清晰,更緊湊。反編譯得知,這兩種寫法最終編譯成同樣的東西,所以本質上一樣的。

闢謠

“Linq被淘汰了”是錯誤的說法,應該是“Linq2SQL被淘汰了”。linq就是微軟發明的這個語法,可以用這種語法操作很多數據,操作SQL數據就是Linq2SQL,linq操作後面學的EntityFramework就是Linq2Entity,linq操作普通.Net 對象就是Linq2Object、Linq操作XML文檔就是Linq2XML。

Linq 基本語法

以from item in items 開始,items爲待處理的集合,item爲每一項的變量名;最後要加上select,表示結果的數據;記得select一定要最後。這是剛用比較彆扭的地方。

看各種用法,不用解析:

var r= from d in dogs select d.Id;
var r= from d in dogs select new{d.Id,d.Name,Desc="一條狗"};

排序

var items = from d in dogs
//orderby d.Age
//orderby d.Age descending
orderby d.Age,d.MasterId descending
select d;

join

var r9 = from d in dogs
join m in masters on d.MasterId equals m1.Id
select new { DogName=d.Name,MasterName=m.Name};

注意join中相等不要用==,要用equals。寫join的時候linq比“lambda”漂亮

group by

var r1 = from p in list
group p by p.Age into g
select new { Age = g.Key, MaxSalary = g.Max(p=>p.Salary), Count = g.Count() };

混用

只有Where,Select,OrderBy,GroupBy,Join 等這些能用linq寫法,如果要用下面的
“Max,Min,Count,Average,Sum,Any,First,FirstOrDefault,Single,SingleOrDefault,Distinct,Skip,Take等”則還要用lambda 的寫法(因爲編譯後是同一個東西,所以當然可以混用)。

var r1 = from p in list
group p by p.Age into g
select new { Age = g.Key, MaxSalary = g.Max(p=>p.Salary), Count = g.Count() };
int c = r1.Count();
var item = r1.SingleOrDefault();
var c = (from p in list
where p.Age>3
select p
).Count();

lambda對linq說:論漂亮我不行,論強大你不行!

C#6.0 語法

  1. 屬性的初始化“public int Age{get;set;}=6”。低版本.Net中怎麼辦?

  2. nameof:可以直接獲得變量、屬性、方法等的名字的字符串表現形式。獲取的是最後一段的名稱。如果在低版本中怎麼辦?

    class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person();
            string s1 = nameof(p1);
            string s2 = nameof(Person);
            string s3 = nameof(p1.Age);
            string s4 = nameof(Person.Age);
            string s5 = nameof(p1.F1);
            Console.ReadKey();
        }
    }
    public class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public void Hello()
        {
        }
        public static void F1()
        {
        }
    }
    

    好處:避免寫錯了,可以利用編譯時檢查。

    應用案例:ASP.Net MVC 中的[Compare(“BirthDay”)]改成[Compare(nameof(BirthDay))]

  3. ??語法:int j= i??3; 如果i爲null則表達式的值爲3,否則表達式的值就是i的值。如果在低版本中怎麼辦?int j = (i== null)?3:(int)i;

    應用案例:string name = null;Console.WriteLine(name??“未知”);

  4. ?.語法:string s8 = null;string s9 = s8?.Trim(); 如果s8爲null,則不執行Trim(),讓表達式的結果爲null。在低版本中怎麼辦?

    string s9=null;if(s8!=null){s9=s8.Trim();};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章