一步一步学Entity Framework 4x 2.docx
- 文档编号:17343543
- 上传时间:2023-07-24
- 格式:DOCX
- 页数:17
- 大小:20.66KB
一步一步学Entity Framework 4x 2.docx
《一步一步学Entity Framework 4x 2.docx》由会员分享,可在线阅读,更多相关《一步一步学Entity Framework 4x 2.docx(17页珍藏版)》请在冰点文库上搜索。
一步一步学EntityFramework4x2
上一期博客末尾给出了一个静态类,四个静态方法。
这有什么用呢?
在继续进行其他内容前,我们先利用这些静态方法为数据库生成基础数据。
按照ADO.NET的常规方法,需要先建立连接,创建DataSet或DataReader对象,构造SQL语句,然后执行SQLCommand命令进行作业。
现在有了EF,这些步骤全部省掉,EF的内部已经自动实现了这些步骤,我们所要做的只是去调用刚刚定义的几个方法。
在项目上新建一个文件夹,命名为Presenter,用来包含一些与用户交互操作的方法,以便Main函数进行调用。
在Presenter文件中下新建一个类,命名为AddDataView.cs,该类就包含一个方法,用以向数据内插入数据:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingProductEFDemo.Business;
namespaceProductEFDemo.Presenter
{
publicstaticclassAddDataView
{
publicstaticvoidAddAllData()
{
try
{
//添加单位数据
InsertData.AddProudctUnit();
Console.WriteLine("产品单位测试数据插入成功!
");
//添加产品大类数据
InsertData.AddProductBigType();
Console.WriteLine("产品大类测试数据插入成功!
");
//添加产品小类数据
foreach(varproductBigTypeinSearchData.GetAllProductBigType())
{
InsertData.AddProductSmallType(productBigType.ProductBigTypeId);
}
Console.WriteLine("产品小类测试数据插入成功!
");
//添加产品数据
foreach(varproductSmallTypeinSearchData.GetAllProductSmallType())
{
foreach(varproductUnitinSearchData.GetAllProductUnit())
{
InsertData.AddProduct(productUnit.ProductUnitId,productSmallType.ProductSmallTypeId);
}
}
Console.WriteLine("添加产品测试数据成功!
");
}
catch(System.Exceptionex)
{
Console.WriteLine(String.Format("发生错误,错误信息为:
{0}",ex.Message);
}
}
}
}
该类中调用的三个方法:
GetAllProductBigType(),GetAllProductUnit(),GetAllProductSmallType()代码如下,由于这些是查询的内容,相关信息后面再详细介绍。
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingProductEFDemo.Models;
namespaceProductEFDemo.Business
{
publicstaticclassSearchData
{
publicstaticList
{
using(varctx=newProductsEntities())
{
returnctx.ProductBigType.ToList();
}
}
publicstaticList
{
using(varctx=newProductsEntities())
{
returnctx.ProductUnit.ToList();
}
}
publicstaticList
{
using(varctx=newProductsEntities())
{
returnctx.ProductSmallType.ToList();
}
}
}
}
代码没有什么可介绍的,注意有关命名空间的引用。
现在开始调用,在项目的Program.cs的Main方法里调用刚刚定义的AddAllData方法:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingProductEFDemo.Presenter;
namespaceProductEFDemo
{
classProgram
{
staticvoidMain(string[]args)
{
AddDataView.AddAllData();
Console.ReadKey();
}
}
}
注意引用ProductEFDemo.Presenter命名空间。
生成并运行程序,
打开SqlSeverManagementStudio,展开表,发现数据已经全部插入了:
你猜猜使用上述代码一共生成了多少条Product数据?
到目前为止,一句SQL代码都没有写,写的代码都是纯粹的C#代码,而且还有额外的IDE代码提示,是不是很爽?
强烈建议不要拷贝代码,而是一行行输入,这样才能感受到书写代码的快乐。
5、数据查询
现在有了数据,就可以随心所欲地进行查询了。
这里先对前面调用的GetAllProductBigType(),GetAllProductUnit(),GetAllProductSmallType()作一个解释:
前面三个方法是获取集合性质数据的典型方法,使用的是ToList()扩展方法(关于扩展方法请自已去MSDN查去,我觉得内置的扩展方法就够用了,暂时还不想去自定义!
),就可以将实体类的数据进行序列化,成为List范型类,List范型类很好用,可以直接绑定为很多集合类控件的数据源,不管你是用WinForm,还是.NetMVC或是WPF,SIlverlight等,都会广泛地用到,但这超出了我想表达内容的范围,就不赘述了。
下面就Linq查询作一介绍。
原来我对Linq很抵触,在《C#入门经典》读到这一章的时候,我选择的是跳过,不去看它。
后来有时间再翻阅书的时候,惊讶地发现我错过了多么美丽的风景!
太简洁,太优雅了!
真心感谢微软,推出了这么好用的工具和语法。
。
。
好了,不吹捧微软了,我们还是先来了解一下Linq的基本知识:
所有的的Linq都是引用自System.Linq名称空间的类,因此在使用前要检查是否引用该名称空间,实际上VS在创建类的模板里已经默认添加了这个引用,如果没有请自行添加。
Linq用于查询数据的语法有两种,一种称为查询语法,有点类似于Sql语句,与Sql语句不同的地方是from在前,select在后,from,select,where,distinct,join(注意全部为小写)现在已经成为C#的关键字,专门用于Linq查询,这种方法一般是首选方法,因为它一般更容易理解,但是可惜的是,Linq的全部功能不能由查询语法实现(比如前面的ToList方法在LInq里没有对应关键字),需要借助于另一种语法,称为方法语法,相比而言,方法语法使用起来稍微难理解一点,但是方法语法的优点是比较简洁,代码更优雅。
下面两种方法都介绍,可以先用查询语法,熟练以后可以试试方法语法,其实也挺好的!
1)简单查询:
场景是这样的,需要从ProductBigType类中查询出包含数字“7”的记录,可以这样写:
using(varctx=newProductsEntities())
{
varresult=fromcinctx.ProductBigType
wherec.ProductBigTypeName.Contains("7")
selectc;
returnresult.ToList();
}如果采用方法语法则可以简化为(为代码简洁起见,后面不再引用using字句):
returnctx.ProductBigType.Where(c=>c.ProductBigTypeName.Contains("7")).ToList();返回的记录是一样的,只不过方法更优雅;
2)数据排序
查询语法使用orderby关键字,如果采用降序,可以添加descending关键字;下面示例的场景是这样的,需要从查询出的所有的ProductBigType中查询出首个单词为“产品”的记录(其实就是全部记录),按降序排序,代码如下:
查询语法:
varresult=fromcinctx.ProductBigType
wherec.ProductBigTypeName.StartsWith("产品")
orderbyc.ProductBigTypeNamedescending
selectc;
returnresult.ToList();方法语法:
returnctx.ProductBigType.Where(c=>c.ProductBigTypeName.StartsWith("产品")).OrderByDescending(c=>c.ProductBigTypeName).ToList();方法语法这种长串的语法称为链式语句,意思像一条长链一样,这是因为所用的方法是扩展方法,都具有相同的类型(实现了IQueryable或IOrderable范型接口),所以可以连接起来;
3)聚合运算符:
用于统计数据,与SQL语句中的相关聚合运算符类似,不同之处这些运算符都是扩展方法,首字母必须大写,常用的聚合扩展方法如下:
Count(),表示结果的个数;
Min(),表示结果中的最小值
Max(),表示最大值;
Average(),表示数据结果的平均值;
Sum(),表示求和;
现在我们想要查询出Product表中ProductBaseValue中最大的数据,就可以这样写:
publicdecimalMaxProductBasePrice()
{
using(varctx=newProductsEntities())
{
varresult=fromcinctx.Product
selectc.ProductBasePrice;
returnresult.Max();
}
}或者采用方法语法:
returnctx.Product.Max(c=>c.ProductBasePrice);4)使用导航属性:
昨天博客发表以后,有园友问为什么要用EntityFramework4.xPOCOGenerator,除了节省力气以外,很重要的一个原因是自已手工写的类经常会忘记导航属性,导致在使用Linq无法导航到所需要的数据,不得不借助join来完成。
实际上,Sql的内联Join关键字完全可以少用或者不用(虽然Linq同样提供了jion关键字和Join扩展方法),而采用一个新扩展方法Include来解决内联的问题,可以顺利地完成导航。
在使用导航属性进行内联接之前,我们先来看看POCO生成的类:
publicpartialclassProduct
{
#regionPrimitiveProperties
publicvirtualSystem.GuidProductId
{
get;
set;
}
publicvirtualstringProductName
{
get;
set;
}
publicvirtualSystem.GuidProductSmallTypeId
{
get{return_productSmallTypeId;}
set
{
if(_productSmallTypeId!
=value)
{
if(ProductSmallType!
=null&&ProductSmallType.ProductSmallTypeId!
=value)
{
ProductSmallType=null;
}
_productSmallTypeId=value;
}
}
}
privateSystem.Guid_productSmallTypeId;
publicvirtualSystem.GuidProductUnitId
{
get{return_productUnitId;}
set
{
if(_productUnitId!
=value)
{
if(ProductUnit!
=null&&ProductUnit.ProductUnitId!
=value)
{
ProductUnit=null;
}
_productUnitId=value;
}
}
}
privateSystem.Guid_productUnitId;
publicvirtualdecimalProductBasePrice
{
get;
set;
}
publicvirtualdecimalProductLosePrice
{
get;
set;
}
#endregion
#regionNavigationProperties
publicvirtualProductSmallTypeProductSmallType
{
get{return_productSmallType;}
set
{
if(!
ReferenceEquals(_productSmallType,value))
{
varpreviousValue=_productSmallType;
_productSmallType=value;
FixupProductSmallType(previousValue);
}
}
}
privateProductSmallType_productSmallType;
publicvirtualProductUnitProductUnit
{
get{return_productUnit;}
set
{
if(!
ReferenceEquals(_productUnit,value))
{
varpreviousValue=_productUnit;
_productUnit=value;
FixupProductUnit(previousValue);
}
}
}
privateProductUnit_productUnit;
#endregion
#regionAssociationFixup
privatevoidFixupProductSmallType(ProductSmallTypepreviousValue)
{
if(previousValue!
=null&&previousValue.Product.Contains(this))
{
previousValue.Product.Remove(this);
}
if(ProductSmallType!
=null)
{
if(!
ProductSmallType.Product.Contains(this))
{
ProductSmallType.Product.Add(this);
}
if(ProductSmallTypeId!
=ProductSmallType.ProductSmallTypeId)
{
ProductSmallTypeId=ProductSmallType.ProductSmallTypeId;
}
}
}
privatevoidFixupProductUnit(ProductUnitpreviousValue)
{
if(previousValue!
=null&&previousValue.Product.Contains(this))
{
previousValue.Product.Remove(this);
}
if(ProductUnit!
=null)
{
if(!
ProductUnit.Product.Contains(this))
{
ProductUnit.Product.Add(this);
}
if(ProductUnitId!
=ProductUnit.ProductUnitId)
{
ProductUnitId=ProductUnit.ProductUnitId;
}
}
}
#endregion
}
其中ProductUnit和ProductSmallType两个属性就是导航属性,这两个属性就可以在实际使用中进行内连接;
比如我们想在控制台中输出若干条Product记录(这里的搜索条件为ProductBasePrice介于49-50之间),要求显示格式为:
产品名称:
XXXX;产品大类:
XXX;产品小类:
XXX;单位:
XXX;基本价格:
XXX;
就需要通过内联从其他表中获取数据,就要用到前面所说的导航属性。
注意到Product表只导航到了ProductSmallType,还需要借助ProductSmallType类导航到ProductBigType。
(如果您不明白,还请再回头看有关数据库表的说明)。
这样代码就可以这样写:
publicstaticList
{
using(varctx=newProductsEntities())
{
returnctx.Product.Include("ProductUnit").
Include("ProductSmallType").Include("ProductSmallType.ProductBigType")
.Where(c=>(c.ProductBasePrice<=50&&c.ProductBasePrice>=49)).ToList();
}
}为了实现前面所说的输出,需要在Presenter文件夹中新建一个类,类中有一个方法对相关数据进行处理:
publicstaticclassProductDeatilView
{
publicstaticvoidShowProductDeatil()
{
foreach(varproductinSearchData.GetProductByPrice())
{
Console.WriteLine(String.Format("产品名称:
{0};产品大类:
{1};产品小类:
{2};单位:
{3};基本价格:
{4};",
product.ProductName,product.ProductSmallType.ProductBigType.ProductBigTypeName,
product.ProductSmallType.ProductSmallTypeName,product.ProductUnit.ProductUnitName,product.ProductBasePrice));
}
}
}
ShowProductDeatile方法只有一个语句,在调用时就使用了Product类的导航属性,只要你想,可以导航到任何数据,但前提是已经将数据都包容进来了。
现在在Main方法中调用ShowProductDeatile方法,输出结果如下:
这个例子使用查询语法也简单不了多少,因为并没有include关键字可用,也必须要使用Include扩展方法。
在此就不举例了。
需要注意的是关于Include扩展方法的参数问题,这个参数是导航的路径,必须是一个字母不错的导航属性名,否则会因为查询不到数据而引发异常。
如果需要通过导航属性再导航到其他相关的导航属性上,则需要使用点式语法,如上例中对ProductBigType导航属性的引用,就需要使用Include("ProductSmallType.ProductBigType")这样的语法;你也可以试试去掉某一个Include语句,试试会发生什么问题。
这个例子还有一种相对麻烦的实现方法,就是新建一个ProductDepository类,将需要展示出的字段放进去,然后使用Linq的join关键字来进行查询,新建的ProductDepository类:
publicclassProductDepository
{
publicstringProductName{get;set;}
publicstringProductBigTypeName{get;set;}
publicstringProductSmallTypeName{get;set;}
publicstringProductUntName{get;set;}
publicdecimalProductBasePrice{get;set;}
}而查询语句如下:
publicstaticList
{
using(varctx=newProductsEntities())
{
varresult=fromcinctx.Product
joindinctx.ProductSmallTypeonc.ProductSmallTypeIdequalsd.ProductSmallTypeId
joineinctx.ProductBigTypeond.ProductBigTypeIdequalse.ProductBigTypeId
joinfinctx.ProductUnitonc.ProductUnitIdequalsf.ProductUnitId
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 一步一步学Entity Framework 4x 一步一步 Entity
![提示](https://static.bingdoc.com/images/bang_tan.gif)