asp.net linq查询环境搭建
本文是以sqlserver2008為數(shù)據(jù)庫,vs2013為開發(fā)工具來介紹的。
要搭建這樣一個數(shù)據(jù)庫的操作環(huán)境,首先建立一個類庫項目
然后在這個類庫項目中添加幾個類:DBDataContext數(shù)據(jù)庫上下文,繼承DbContext(這需要添加EntityFramework和EntityFramework.SqlServer的引用,如果開發(fā)工具是vs2013的話,可以在工具菜單下選擇擴展和更新,在聯(lián)機狀態(tài)下搜索EntityFramework
重啟vs后,工具-》庫程序包管理器-》程序包管理器控制臺,打開控制臺,然后:
新增了一個packages.config文件
在web.config文件里面
再打開項目的引用,就會看到EF已經(jīng)引用進去了。這里一直沒注意是重啟vs之后這個引用就已經(jīng)添加到項目中了呢還是通過上面的操作才最終引用成功了。這個以后要注意一下。OK,在類庫項目中也將這兩個插件引進去吧。
);DBA數(shù)據(jù)庫訪問類,繼承DBDataContext;DBAManager數(shù)據(jù)庫控制類。
DBDataContext:
public class DBDataContext:DbContext{public DBDataContext(): base("defaultDB")//這個defaultDB是配置文件中的數(shù)據(jù)庫連接字符串的名稱 {}protected override void OnModelCreating(DbModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);RegisterModelMapping(modelBuilder);}protected virtual void RegisterModelMapping(DbModelBuilder modelBuilder){}}數(shù)據(jù)庫的連接字符串:由于數(shù)據(jù)庫是放在本機的,所以server等于.,
<connectionStrings><add name="defaultDB" connectionString="Server=.;Database=MRS;uid=sa;pwd=123456" providerName="System.Data.Sqlclient"></add> </connectionStrings>
?
DBA:
public class Dba : DBDataContext{private const string TbaleArea = "Area";}?
DBAManager: public class DBAManager{protected Dba DataAccessContext = new Dba();public DBAManager(){}public DBAManager(Dba context){DataAccessContext = context;}}?
剩下的就是建立實體類了,需要查詢什么數(shù)據(jù)就建立一個類,類里面的每個屬性值表示數(shù)據(jù)庫表中的一列。比如,數(shù)據(jù)庫里面有一個名為Area的表,那么就建立一個名為Area的類,里面屬性的類型與數(shù)據(jù)庫表中的類型一致。
public class Area
{
public int AreId{get;set;}
public int AreChildNo{set;get;}
public int AreParentNo{set;get;}
public string AreName{set;get;}
public string AreCreaterNo{set;get;}
public DateTime AreCreateTime{set;get;}
public int AreIsChecked{set;get;}
public int AreDelState { set; get; }
}
類中的屬性表示數(shù)據(jù)庫表中的列,這里可以不用全部寫完,只需要寫出需要查詢的列就可以。然后在DBA類中添加一條語句:public DbSet<Area> myArea{ get; set; },然后重寫DBA的父類的RegisterModelMapping函數(shù):
protected override void RegisterModelMapping(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.RegisterModelMapping(modelBuilder);
#region 行政區(qū)劃表
modelBuilder.Entity<Area>().ToTable("Area");//這里的Area表示數(shù)據(jù)庫里面的表名
modelBuilder.Entity<Area>().HasKey(a => a.AreId);
modelBuilder.Entity<Area>().Property(a => a.AreId);
modelBuilder.Entity<Area>().Property(a => a.AreName).IsRequired();
modelBuilder.Entity<Area>().Property(a => a.AreChildNo).IsRequired();
modelBuilder.Entity<Area>().Property(a => a.AreParentNo).IsRequired();
modelBuilder.Entity<Area>().Property(a => a.AreCreaterNo);
modelBuilder.Entity<Area>().Property(a => a.AreCreateTime);
modelBuilder.Entity<Area>().Property(a => a.AreDelState);
modelBuilder.Entity<Area>().Property(a => a.AreIsChecked);
#endregion
}
在DBAManager類中創(chuàng)建用于查詢數(shù)據(jù)的函數(shù):
/// <summary>/// 獲取所有行政區(qū)劃/// </summary>/// <returns></returns>public virtual IList<Area> GetAreas(int AreChildNo=0){var query =?from a in DataAccessContext.myArea select a;if (AreChildNo> 0){query = query.Where(a => a.AreChildNo<= AreChildNo);}return query.ToList();}
然后編譯這個類庫,同時在網(wǎng)站項目中添加這個類庫的引用,同時還要添加EntityFramework.SqlServer.dll和EntityFramework.dll的引用。添加好了之后,新建一個網(wǎng)頁,在網(wǎng)頁后臺代碼中查詢數(shù)據(jù)庫:
public partial class WebForm1 : System.Web.UI.Page{public DBAManager dbam = new DBAManager();protected void Page_Load(object sender, EventArgs e){IList<Area> Areas = dbam.GetAreas();}}?到此,整個查詢環(huán)境就搭建起來了。整個過程不需要手動的在數(shù)據(jù)庫里面去創(chuàng)建表,也不需要你手動的去建立什么數(shù)據(jù)庫,當程序運行起來后,只要執(zhí)行了上面的查詢操作,系統(tǒng)會自動根據(jù)設置在sqlserver里面創(chuàng)建數(shù)據(jù)庫并且創(chuàng)建所有的表,當然如果數(shù)據(jù)庫里面需要什么函數(shù),或者存儲過程什么的,能不能自動創(chuàng)建,這個暫時不清楚。還有種情況就是在創(chuàng)建了數(shù)據(jù)庫后,如果修改了模型,比如在area表中想添加一列或刪除一列,那么除了需要修改對應的模型外,還要完成code first遷移工作,具體的參照:https://msdn.microsoft.com/zh-cn/data/jj591621。但是這種方式就是在每次修改了模型后,都要做重復的工作,更好的方式應該是修改模型后,在運行的時候,系統(tǒng)自動根據(jù)模型的改變來修改數(shù)據(jù)庫結構,并保留數(shù)據(jù)庫中沒有變動的數(shù)據(jù)。
接下來再研究各種常用的查詢以及修改刪除。
1、單表查詢,也就是只在一個表中查詢數(shù)據(jù):
var query = from a in DataAccessContext.myAreawhere a.AreId<10 where a.AreParentNo !=0select a;var query = from a in DataAccessContext.myAreawhere a.AreId<10 && a.AreParentNo !=0select a;上面的兩段查詢代碼是等價的,在linq查詢中,對于多條件的查詢不能用and或or來連接,而應該像上面那樣才可以。個人覺得,第二種方式看起來更像sql語句的語法規(guī)則。
var query = from a in DataAccessContext.myAreawhere a.AreId<10 || (a.AreId >=20 && a.AreId<30)orderby a.AreId descending//這是降序select a;升序是ascending。linq查詢除了將查詢條件按照上面的方式設置外,還可以這樣做:IList<Area> f = query.Where(a => a.AreId % 2 == 0).ToList();如果是多個查詢條件的話,這種方式可以這樣設置:
IList<Area> f = query.Where(a => a.AreId % 2 == 0 && a.AreId>4).ToList(); 或 IList<Area> f = query.Where(a => a.AreId % 2 == 0).Where(b=>b.AreId>4).ToList();//對于這種方式的or條件該怎么設置,暫時還沒學會。模糊查詢用Contains函數(shù),eg:where a.AreName.Contains("城")。
總結:通過上面的例子,可以看到,linq的查詢條件遵循的語法是C#或VB等編程語言的語法,比如a.AreId 是一個int型的數(shù)據(jù),只要用它按照編程語言的語法規(guī)則來做運算且運算結果是bool型,那么就可以作為where條件來使用。這樣一來,對于一個根本不懂sql語句的菜鳥,查詢數(shù)據(jù)庫就不在是問題。
2、多表查詢,以最簡單的兩個表為例。
假如數(shù)據(jù)庫中有這樣兩個表ActiveCourseDetail和ActiveCourse。這兩個表是一個多對一的關系,關聯(lián)的字段是ACID,兩個表都有這個字段。首先還是要建立表的實體類,并在Dba類中映射數(shù)據(jù)庫,最后在DBAManager類中寫查詢的函數(shù)。
var query=from ac in DataAccessContext.myActiveCoursejoin acd in DataAccessContext.myActiveCourseDetail on ac.ACID equals acd.ACIDselect ac;//這個查詢語句等于下面的sql語句 select ac.* from ActiveCourse ac ,ActiveCourseDetail acd where ac.ACID=acd.ACID?如果說,查詢的條件需要兩個字段分別對應相等,可以如下:
var query=from ac in DataAccessContext.myActiveCoursejoin acd in DataAccessContext.myActiveCourseDetail on ac.ACID equals acd.ACIDwhere ac.ACIntegral==acd.AcdYuYueselect ac;還可以:
var query = from ac in DataAccessContext.myActiveCoursejoin acd in DataAccessContext.myActiveCourseDetailon new { a = ac.ACID, b = ac.ACIntegral } equals new { a = acd.ACID, b = acd.AcdYuYue }select ac;這里面的a和b是隨便寫的,沒有實際的意義。上面的語句查詢出來的結果中有重復的數(shù)據(jù),為了去掉重復的數(shù)據(jù),只保留一個,需要用到Distinct函數(shù)。即:query.Distinct().ToList()
上面的查詢都是查詢的一個表的所有字段,而且查詢出來的結果在轉換成集合時,還必須指定集合的類型,這是很不方便的。為了對查詢的結果能夠自由組合,獲取我們想要的字段,可以按下面的方式處理:
var query = from ac in DataAccessContext.myActiveCoursejoin acd in DataAccessContext.myActiveCourseDetailon new { a = ac.ACID, b = ac.ACIntegral } equals new { a = acd.ACID, b = acd.AcdYuYue }select new {c=ac.ACName,d=ac.ACTeacherID,f=acd.AcdYuYue,g=acd.Remark};var name = query.Distinct().ToList();上面的語句分別從兩個表中各取兩個字段來組合成我想要的查詢結果,然后將其轉換為集合的時候,直接用var來定義接收變量,這樣就不用去管具體的數(shù)據(jù)類型了。這里的變量name就是一個數(shù)組集合。下面是name的數(shù)據(jù)結構,這種數(shù)據(jù)可以通過轉換為jason字符串來讀取里面的數(shù)據(jù)。如果是在jquery中的話,還可以將jason還原為對象。
三個表關聯(lián)查詢:
var query = from ac in DataAccessContext.myActiveCoursejoin acd in DataAccessContext.myActiveCourseDetailon new { a = ac.ACID, b = ac.ACIntegral } equals new { a = acd.ACID, b = acd.AcdYuYue } join cus in DataAccessContext.myCustomeron acd.CusID equals cus.CusID//這里要注意,cus.CusID必須位于equals右邊select new {c=ac.ACName,d=ac.ACTeacherID,f=acd.AcdYuYue,g=acd.Remark,cusname=cus.CusName};關于group by 的用法:
var query = from ac in DataAccessContext.myActiveCoursejoin acd in DataAccessContext.myActiveCourseDetailon new { a = ac.ACID, b = ac.ACIntegral } equals new { a = acd.ACID, b = acd.AcdYuYue } join cus in DataAccessContext.myCustomeron acd.CusID equals cus.CusID//這里要注意,cus.CusID必須位于equals右邊group ac by new {ac.ACName,ac.ACTeacherID,ac.ACID,acd.Remark} into sselect new { c = s.Key.ACName, d = s.Key.ACTeacherID, f = s.Key.Remark, i = s.Key.ACID, ss = s.Sum(t => t.ACIntegral) } ; SELECT ac.ACName,ac.ACTeacherID,ac.ACID,acd.Remark,sum(ac.ACIntegral) ssFROM ActiveCourse ac,activecoursedetail acd,Customer cus where ac.ACID=acd.ACID and ac.ACIntegral=acd.AcdYuYue and acd.CusID=cus.CusID group by ac.ACName,ac.ACTeacherID,ac.ACID,acd.Remark,ac.ACIntegral上面的sql語句和linq語句是等效的。
下面來看看如何實現(xiàn)左連接查詢。有時候我們需要查詢?nèi)缦聢D所示的結果:
?
var query = from cus in DataAccessContext.myCustomerjoin i in DataAccessContext.myIntegral on cus.CusVipCardNo equals i.ItgVipCardNo into newtfrom x in newt.DefaultIfEmpty()orderby cus.CusVipCardNo descending//這是降序select new { a = cus.CusName, b = cus.CusVipCardNo, c = x == null ?null : x.ItgCusName };這段代碼有個地方要特別注意,就是如果x.ItgCusName的在數(shù)據(jù)庫中的類型不是varchar,而是float類型,那么在定義實體類的時候,這個字段的類型必須定義為double,否則上面的語句會報錯。
對于一個用慣了sql語句查詢的人來說,用linq來處理一些復雜的查詢是比較讓人頭疼的。所幸,在linq中還是可以調(diào)用存儲過程,這樣就將復雜的sql語句封裝到存儲過程中,然后再在linq查詢環(huán)境下調(diào)用存儲過程即可。
linq調(diào)用存儲過程有兩種方式(這是目前我所接觸到的)。一種是通過創(chuàng)建一個linq to sql類,后綴是.dbml。創(chuàng)建好了以后,在vs左邊的服務器資源管理器中找到你的數(shù)據(jù)連接(這個連接是在前面搭建linq查詢環(huán)境的時候就自動配置好了的,它的名稱和配置文件中的連接字符串的名稱一樣),找到你創(chuàng)建的存儲過程,將其拖到linq to sql類中,系統(tǒng)會自動的在這個類中創(chuàng)建一個和存儲過程名稱相同的函數(shù)。然后你要調(diào)用這個存儲過程的時候,只需要創(chuàng)建一個linq to sql類的實例,然后像調(diào)用函數(shù)一樣調(diào)用存儲過程就可以了。這種方式是非常簡單。
下面主要介紹一下另一種方式,這種方式不需要去創(chuàng)建一個linq to sql類。
首先,在sqlserver中創(chuàng)建一個存儲過程ABC,它的作用就是查詢area表中的所有數(shù)據(jù),怎么創(chuàng)建存儲過程,在這里就不啰嗦了。然后,在vs中創(chuàng)建一個函數(shù)用來調(diào)用存儲過程:
public void GetAreas(){string sql = "Execute ABC ";IList<Area> a = DataAccessContext.Database.SqlQuery<Area>(sql).ToList();}這里主要是用的?DataAccessContext.Database.SqlQuery來實現(xiàn)存儲過程的調(diào)用的,這只是一個沒有參數(shù)的存儲過程的調(diào)用,而且返回的結果集是用的area表的實體類的集合來接收的,當然如果結果集是多個表的字段自由組合的,那也需要定義一個包含同樣字段的類來接收。這也是linq不好的地方,每次查詢一個結果集都必須要有相應的類型,而不像sql語句查詢那樣直接放到dataset中。
調(diào)用帶有參數(shù)的存儲過程:
string sql = "Execute SendStateInfoSearch @word,@areaCode,@depCode";SqlParameter txt = new SqlParameter { ParameterName = "@word", Value = word };SqlParameter area = new SqlParameter { ParameterName = "@areaCode", Value = areaCode };SqlParameter dep = new SqlParameter { ParameterName = "@depCode", Value = depCode }; List<BWSStateEntity> results = DataAccessContext.Database.SqlQuery<BWSStateEntity>(sql, txt, area, dep).ToList<BWSStateEntity>();接下來將介紹linq對數(shù)據(jù)的添加,修改與刪除
首先看看如何修改數(shù)據(jù):
public void getDB(){var query = from cus in DataAccessContext.myCustomerwhere cus.CusName.Contains("高")select cus;IList<Customer> people = query.ToList();Customer p1 = people[0];p1.CusRemark = "ffsfasdfa";DataAccessContext.myCustomer.Attach(p1);DataAccessContext.Entry(p1).State = System.Data.Entity.EntityState.Modified;DataAccessContext.SaveChanges();}代碼中,首先是要查出需要修改的數(shù)據(jù),通過表的實體對象來完成修改,然后調(diào)用DataAccessContext的相關方法來完成修改,這里只是修改了數(shù)據(jù)表中的一行數(shù)據(jù),如果遇到需要批量修改數(shù)據(jù)的情況那就有點悲劇了,簡單一點的就是先查出要修改的所有數(shù)據(jù),然后用for循環(huán)來修改,這實際上根本就不是批量修改。查看了一下網(wǎng)上提供的方法,感覺都太復雜了,咱是簡單的人,只做簡單的事,所以只好在需要批量修改的情況下直接用存儲過程得了。
添加數(shù)據(jù):代碼和上面的差不多,只不過不需要從數(shù)據(jù)庫查詢數(shù)據(jù)了,需要的是創(chuàng)建一個新的實體對象p1,然后
DataAccessContext.myCustomer.Add(p1);DataAccessContext.Entry(p1).State = System.Data.Entity.EntityState.Added;DataAccessContext.SaveChanges();?刪除:
var query = from cus in DataAccessContext.myCustomerwhere cus.CusName.Contains("高")select cus;Customer people = query.FirstOrDefault();DataAccessContext.myCustomer.Attach(people);DataAccessContext.Entry(people).State = System.Data.Entity.EntityState.Deleted;DataAccessContext.SaveChanges();在linq環(huán)境下直接使用sql語句:
string sql = "select * from Customer where CusName =@name";IList<Customer> cus = DataAccessContext.Database.SqlQuery<Customer>(sql, new SqlParameter("@name", "曹露")).ToList();如果sql條件中有多個參數(shù),可以將這些參數(shù)到SqlParameter的數(shù)組中,比如:
List<SqlParameter> param = new List<SqlParameter>();param.Add(new SqlParameter("@name", "曹露"));然后在調(diào)用SqlQuery的時候,第二個參數(shù)用param.ToArray()。
上面是執(zhí)行查詢語句的方式,如果是執(zhí)行添加,修改或刪除的話,用DataAccessContext.Database.ExecuteSqlCommand(sql,param.ToArray()),它的返回值是一個整數(shù)。但是,即使在這里用sql語句來做查詢,但如果查詢的結果集是幾個表中的一部分字段,那么查詢出來的結果就是一個匿名類,如果不定義相應的類的話,這個匿名類似乎不好用。
轉載于:https://www.cnblogs.com/jin-/p/4649041.html
總結
以上是生活随笔為你收集整理的asp.net linq查询环境搭建的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RedHat7.1 安装Oracle12
- 下一篇: Sidebar Enhancements