實體類的繼承
所有實體類都會有一些公共屬性,可以把這些屬性定義到一個父類中。比如:
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:
- DbQuery 中的:DbQuery AsNoTracking()、DbQuery Include(string path)
- 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 語法
-
屬性的初始化“public int Age{get;set;}=6”。低版本.Net中怎麼辦?
-
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))]
-
??語法:int j= i??3; 如果i爲null則表達式的值爲3,否則表達式的值就是i的值。如果在低版本中怎麼辦?int j = (i== null)?3:(int)i;
應用案例:string name = null;Console.WriteLine(name??“未知”);
-
?.語法:string s8 = null;string s9 = s8?.Trim(); 如果s8爲null,則不執行Trim(),讓表達式的結果爲null。在低版本中怎麼辦?
string s9=null;if(s8!=null){s9=s8.Trim();};