[以前学习Linq To Entities 时自己写的点心得资料,放在这里供初学者参考]

1、先实例化entities对象(注意释放所占空间,结合using 使用)

2、实例化的entities对象中的表的实体,生成对象a,返回类型为objectquery<表实体类名>

3、使用linq对a进行查询,返回类型为iqueryable<你所需要的查询类型(若你只需要一个为字符串类型的字段,可为string,若你需要查出整个表的字段,则可以为表的实体类型。)>生成对象b.
(若只需要查出表中部分字段且大于一个时可以 var 类型  

代码
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
IQueryable
<SalesOrderHeader> ordersQuery = AWEntities.Contact
.Where(c
=> c.LastName == "Zhou")
.SelectMany(c
=> c.SalesOrderHeader);
foreach (var order in ordersQuery)
{
Console.WriteLine(
"Order ID: {0}, Order date: {1}, Total Due: {2}",
order.SalesOrderID, order.OrderDate, order.TotalDue);
}
}

 

 

4、查询语句可以使用linq也可以使用,其自带的如select之类的查询函数。

代码
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
ObjectQuery
<SalesOrderHeader> sales = AWEntities.SalesOrderHeader;

IQueryable
<int> salesInfo =
from s
in sales
where s.TotalDue >= 200
select s.SalesOrderID;

Console.WriteLine(
"Sales order info:");
foreach (int orderNumber in salesInfo)
{
Console.WriteLine(
"Order number: " + orderNumber);
}
}

 

 

5、与返回一系列值的延迟执行查询相反,返回单一实例值的查询将立即执行。Average、Count、First 和 Max 是单一实例查询的一些示例。这些查询立即执行,因为查询必须生成序列才能计算单一实例结,而查询出多个时都是在后面的foreach中执行。前面的b只是一个查询对象,里面并没有真正的数据,若需要配合缓存一起使用需要全部查出时,按msdn上的说法可以使用tolist和toarray直接查出。可以对查询或查询变量调用 ToList、ToDictionary 或 ToArray 方法。下面的示例使用 ToArray 方法立即将序列转换为数组。

代码
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
ObjectQuery
<Product> products = AWEntities.Product;

Product[] prodArray
= (
from product
in products
orderby product.ListPrice descending
select product).ToArray();

Console.WriteLine(
"Every price from highest to lowest:");
foreach (Product product in prodArray)
{
Console.WriteLine(product.ListPrice);
}
}

 

 

 

6、

 

代码
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
IQueryable
<SalesOrderHeader> ordersQuery = AWEntities.Contact
.Where(c
=> c.LastName == "Zhou")
.SelectMany(c
=> c.SalesOrderHeader);

foreach (var order in ordersQuery)
{
Console.WriteLine(
"Order ID: {0}, Order date: {1}, Total Due: {2}",
order.SalesOrderID, order.OrderDate, order.TotalDue);
}
}

 

 

selectmany()返回的是一个一维序列,而select()返回的是一张表。(msdn对比得到)

7、下面的示例包含一个自定义类 MyContact,该类有一个 LastName 属性。如果设置 LastName 属性,count 变量就会递增。如果执行以下两个查询,则第一个查询将使 count 递增,而第二个查询不会。这是因为:在第二个查询中,将从结果中投影 LastName 属性,而绝不会创建 MyContact 类,因为这不是对存储区执行查询所必需的。

代码
public static int count = 0;

static void Main(string[] args)
{
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
var query1
= AWEntities
.Contact
.Where(c
=> c.LastName == "Jones")
.Select(c
=> new MyContact { LastName = c.LastName });

// Execute the first query and print the count.
query1.ToList();
Console.WriteLine(
"Count: " + count);

//Reset the count variable.
count = 0;

var query2
= AWEntities
.Contact
.Where(c
=> c.LastName == "Jones")
.Select(c
=> new MyContact { LastName = c.LastName })
.Select(my
=> my.LastName);

// Execute the second query and print the count.
query2.ToList();
Console.WriteLine(
"Count: " + count);

}
Console.WriteLine(
"Hit enter...");
Console.Read();
}

 

 

8、对象上下文中的对象是实体类型的实例,表示数据源中的数据。在对象上下文中可以修改、创建和删除对象,对象服务会跟踪对这些对象所做的更改。调用 SaveChanges 方法时,对象服务会生成并执行一些命令,这些命令将对数据源执行等效的插入、更新或删除语句。有关更多信息,请参见保存更改和管理并发(实体框架)。

例如,假定执行返回 SalesOrderHeader 对象和相关 SalesOrderDetail 对象集合的查询。您可以循环访问该集合并执行下列操作:

?更改订单的 ShipDate 属性。

?通过调用 DeleteObject 方法删除特定项。

?通过调用 Add 方法将某一行项添加到订单中。

?对对象上下文调用 SaveChanges 方法以将对象更改保存回数据源。

下面的示例演示对象上下文中的对象所发生的各种更改:

9、如果应用程序需要在实体框架中多次执行结构类似的查询,通常可以通过仅编译查询一次并在每次执行时使用不同参数的方法来提高性能。例如,某应用程序要检索特定城市的所有客户,而该城市是运行时由用户在窗体中指定的。LINQ to Entities 支持使用已编译的查询用于此目的。Compile 方法编译的 LINQ to Entities 查询表达式由一个泛型 Func 委托(如 Func)表示。查询表达式通常都可以封装一个 ObjectContext 参数、一个返回参数和三个查询参数。如果需要的查询参数不止三个,则可以创建一个结构并用其属性表示查询参数。然后,该结构上的这些属性在经过设置之后就可以用于查询表达式中。(MSDN上所说的没看懂)

10、如果在排序操作之后执行了任何其他操作,则不能保证这些附加操作中会保留排序结果。这些操作包括 Select 和 Where 等,采用表达式作为输入参数的 First 和 FirstOrDefault 方法不保留顺序。如下面的示例所示:

代码
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
// In this query, the ordering is not preserved because Distinct
// is called after OrderByDescending.
IQueryable<string> productsList = AWEntities.Product
.OrderByDescending(p
=> p.Name)
.Select(p
=> p.Name)
.Distinct();

Console.WriteLine(
"The list of products:");
foreach (string productName in productsList)
{
Console.WriteLine(productName);
}

// In this query, the ordering is preserved because
// OrderByDescending is called after Distinct.
IQueryable<string> productsList2 = AWEntities.Product
.Select(p
=> p.Name)
.Distinct()
.OrderByDescending(p
=> p);

Console.WriteLine(
"The list of products:");
foreach (string productName in productsList2)
{
Console.WriteLine(productName);
}
}

 

 

11、不保留嵌套查询中的排序。在下面的示例中,调用第二个 Select 方法时,按姓氏排序的结果将会丢失:

代码
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
// Return all contacts, ordered by last name.
IQueryable<string> contacts = AWEntities.Contact
.OrderBy(x
=> x.LastName)
.Select(x
=> x)
.Select(x
=> x.LastName);

foreach (var c in contacts)
{
Console.WriteLine(c);
}
}

 

 

12、对于下面的操作并不能像网上所说的那样,能够验证数据的并发操作引起的数据更新时的不可重读。因为在成的sql语句中只对已经修改了其值的实体类中的属性进行updata set

        
        

代码
using(cms_dbEntities content=new cms_dbEntities())
{
content.Connection.Open();
using(var trans=content.Connection.BeginTransaction(IsolationLevel.Serializable))
{
try
{
int i = Convert.ToInt32(textBox1.Text);
IQueryable
<lxp_content> select = from a in content.lxp_content
where a.C_id == i
select a;
IQueryable
<lxp_content> select1 = from b in content.lxp_content
where b.C_id == i + 1
select b;

foreach (var s in select)
{
content.DeleteObject(s);
}
foreach (var s in select1)
{
content.DeleteObject(s);
}
content.SaveChanges();
trans.Commit();
button2_Click(sender, e);
}
catch
{
trans.Rollback();
button2_Click(sender, e);
}
}
}
}
要想验证并发的不可重读性可以读出一个字段进行如加减之类的操作
{
cms_dbEntities content
= new cms_dbEntities();
cms_dbEntities content2
= new cms_dbEntities();
IQueryable
<lxp_content> select = from a in content.lxp_content
where a.C_id == 60
select a;
IQueryable
<lxp_content> select2 = from b in content2.lxp_content
where b.C_id == 60
select b;
foreach (var a in select2)
{
a.C_hits
= a.C_hits + 10;
}
foreach (var s in select)
{
s.C_hits
= s.C_hits + 100;
}
// MessageBox.Show(content2);
content2.SaveChanges();
try
{
content.Refresh(RefreshMode.StoreWins,select);
foreach (var s in select)
{
s.C_hits
= s.C_hits + 100;
}
content.SaveChanges();
}
catch (OptimisticConcurrencyException ex)
{

return;
}
}

 

 

这里,Refresh的第一个参数值得注意一下,它是一个枚举值,有两个选项:StoreWins或者是ClientWins。见名知义,如果是StoreWins,那么,Refresh以后,laptop2的值将与数据库里的对应记录的值一致(修改会丢失);而如果ClientWins,则laptop2的值保持,并且提交以后,会把objContext1提交的修改覆盖。 其实,这两种方法均不完美,总会导致一部分修改丢失。但是,这总比在不知情的情况下的覆盖要好。另外,需要说明,上面的方法,只是对并发冲突的一种模拟,这样的模式,在处理并发冲突时会有问题。一般的处理方法是,当检测到并发冲突时,提示用户会重新从数据库载入数据,然后,让用户在新数据的情况下重新修改后再次提交,直到不再有并发冲突发生。这样,看似可能成为一个无穷尽的痛苦的过程,但实际上,由于这种处理方式是基于对并发冲突的乐观估计来设计的,因此,当我们认为并发冲突很少有可能发生时,这种处理方式可以有效避免数据被无意识的覆盖问题。

这些属性将会加入到T-SQL脚本的WHERE子句部分,用来比较客户端的值和数据库端的值。
示例代码:       
 

代码
public void UpdateProduct()
{
Product product
= context.Product.FirstOrDefault(p => p.ProductID == 1004);
if (product != null)
{
product.Color
= "White";
product.StandardCost
= 200;
product.ListPrice
= 250;
}
context.SaveChanges();
}

 

 

正常情况下,不检查并发情况,产生的T-SQL脚本如下:

代码
exec sp_executesql N'update [SalesLT].[Product]set [Color] = @0, [StandardCost] = @1, [ListPrice] = @2where ([ProductID] = @3)',N'@0 nvarchar(5), @1 decimal(19,4), @2 decimal(19,4), @3 int', @0=N'White', @1=1000.0000, @2=2000.0000,@3=1004

 

 

在设置Product实体的Color属性的Concurrency Mode 为Fixed,你会发现生成的T-SQL脚本中,Where子句中增加了对Color 字段的检查:

代码
exec sp_executesql N'update [SalesLT].[Product]set [Color] = @0, [StandardCost] = @1, [ListPrice] = @2where (([ProductID] = @3) and ([Color] = @4))',N'@0 nvarchar(5), @1 decimal(19,4), @2 decimal(19,4), @3 int, @4 nvarchar(5)', @0=N'White', @1=200.0000, @2=250.0000, @3=1004, @4=N'White'

 

 

解决并发冲突如下的示例代码演示如何解决并发冲突。当发生并发冲突时,将抛出OptimisticConcurrencyException 异常,可以通过调用Object Context 的Refresh() 方法,传入RefreshMode.ClientsWins 选项,来解决冲突。这将重新执行LINQ to Entities 查询,并覆盖数据库的值,随后再次调用SaveChanges() 方法。模拟并发冲突及其脚本:       
 

代码
public void UpdateProduct()
{
Product product1
= context.Product.FirstOrDefault(p => p.ProductID == 1004);
if (product1 != null)
{
product1.Color
= "Black";
product1.StandardCost
= 20;
product1.ListPrice
= 25;
}
AdventureWorksLTEntities context2
= new AdventureWorksLTEntities();
Product product2
= context2.Product.FirstOrDefault(p => p.ProductID == 1004);
if (product2 != null)
{
product2.Color
= "Blue";
product2.StandardCost
= 18;
product2.ListPrice
= 30;
}
// Save changes of first DataContext
context.SaveChanges();
try
{
context2.SaveChanges();
}
catch (OptimisticConcurrencyException ex)
{
Console.WriteLine(ex.ToString());
// The concurrently conflict can be resolved by refreshing the DataContext
context2.Refresh(RefreshMode.ClientWins, product2);
// And saving the changes again
context2.SaveChanges();
}
}

 

 

Refresh的第一个参数值得注意一下,它是一个枚举值,有两个选项:StoreWins或者是ClientWins。如果是StoreWins,那么,Refresh以后,product2的值将与数据库里的对应记录的值一致(修改会丢失);而如果ClientWins,则product2的值保持,并且提交以后,会把context提交的修改覆盖。其实,这两种方法均不完美,总会导致一部分修改丢失。但是,这总比在不知情的情况下的覆盖要好。 另外,需要说明,上面的方法,只是对并发冲突的一种模拟,这样的模式,在处理并发冲突时会有问题。一般的处理方法是,当检测到并发冲突时,提示用户会重新从数据库载入数据,然后,让用户在新数据的情况下重新修改后再次提交,直到不再有并发冲突发生。

13、 根据需要,修改映射
由于实体数据模型存在于客户端,故其修改不会对数据库造成影响。也就是说,我们可以根据应用程序的需要,修改映射关系,并且这种修改不会影响数据库。这一特点,会在同一企业不同领域使用共享的数据存储,不同的领域模型的情况下带来受益。我们来试着删除Weight的映射。实在是超级简单啊,在实体上右击,点击"删除",观察一下映射详细信息面板:Weight已经被删除了。

14、一般有多个外键的表  都是主表 、大表   key所在的标都是常量表  我的做法是把这些表先全部读出来  detach 保存在dictionary里面  需要某条的时候  取出来clone, attach为未修改  到当前的context    这样就可以免去每次都去select 一行

15、若要从一的一方查询出多的一方时可以使用一的一方对象.多的一方.Load();查出
 

代码
private void button5_Click(object sender, EventArgs e)
{
using (cms_dbEntities content = new cms_dbEntities())
{
IQueryable
<lxp_content> select = from a in content.lxp_content
where a.C_id == 60
select a;
foreach (var s in select)
{
s.lxp_loat.Load();
foreach (var a in s.lxp_loat)
{
label1.Text
+= a.name;
}
}
}
}

 

 

若要从多的一方查询出多的一方时,使用多的一方.一的一方Reference.Load();即可
       

代码
private void button6_Click(object sender, EventArgs e)
{
using (cms_dbEntities content = new cms_dbEntities())
{
IQueryable
<lxp_loat> select = from a in content.lxp_loat
where a.loat_id == 1
select a;
foreach (var a in select)
{
a.idReference.Load();
label1.Text
+= a.id.C_title;
}
}
}

 

 


16、在实体中建立多对多的关系,进行查询,减少中间的表的实体
先,中间表"NbOS"是不存在的。现实生活中没有这么一个东西代表笔记本与操作系统中的联系。因此,我们做的第一件事,就是把这个中间表删除。 由于中间表被删除,Notebook与InitOS之间的羁绊亦被斩断了。我们需要重新将其建立起来,让他们比以前联系得更紧密。在实体模型设计器上右击选择"添加->关系",出现"Add Association"对话框,见图5,两个端(End)分别设置为"Notebook"和" InitOS"。Multiplicity均设置为Many,Navigation属性可以根据个人喜好设置
 

代码
using (cms_dbEntities content = new cms_dbEntities())
{
IQueryable
<lxp_a> select = from a in content.lxp_a
where a.id == 1
select a;
foreach( var s in select)
{
s.lxp_c.Load();
foreach (var a in s.lxp_c)
{
MTOM.Text
+= a.name + " ";
}
}
}

 

 

17、实体之间的继承关系
当同在一个数据表中的内容根据其中 的一个字段进行区分,若在处理数据时会因此数据的字段不同而处理不同此时可以让它们分别处于不同的实体,然后同时继承一个此从数据库中映射过来的基类,但是在基类中需要删除些因此字段不同而可有可无的字段(如有一字段为性别,这时胡须长度字段,因为是女时此字段就没有)然后根据实际需要在子类加入这些字段。但是值得注意的是一定在设计数据库时把这个字段设计为可空的。查询时在from in 后使用oftype函数,若是基类时就查出所有的。同时还要在子类中设定区分字段的值,只有当此条记录中的此字段为设定好的值时才为此子类。
 

代码
private void button2_Click(object sender, EventArgs e)
{
using (cms_dbEntities content = new cms_dbEntities())
{
var select
= from a in content.lxp_title.OfType<lxp_title>()
select a;
dataGridView1.DataSource
= select;
}
}

private void button3_Click(object sender, EventArgs e)
{
using (cms_dbEntities content = new cms_dbEntities())
{
var select
= from a in content.lxp_title.OfType<over_lxp_title>()
select a;
dataGridView1.DataSource
= select;
}
}

 

 

需要设定over_lxp_title实体中的type值,才能查询出。

18、实体层数据与数据库中数据的同步
第一类:放任不管方式;(完全不考虑同步问题)
第二类:开放式并发处理方式;(在进行并行操作的同时,考虑同步问题,基本上能保证数据的正确同步)
第三类:保守式并发处理方式。 (将并行改为串行操作,完全同步)

19、System.Data.EntityClient 命名空间是 实体框架的 .NET Framework 数据提供程序。EntityClient 提供程序使用存储特定的 ADO.NET 数据提供程序类和映射元数据与实体数据模型进行交互。EntityClient 首先将对概念性实体执行的操作转换为对物理数据源执行的操作。然后再将物理数据源返回的结果集转换为概念性实体。

EntityClient下的类有以下几个:

l          EntityConnection

l          EntityCommand

l          EntityConnectionStringBuilder   //连接字符串构造类

l          EntityParameter

l          EntityDataReader 

l          EntityParameterCollection

l          EntityProviderFactory

l          EntityTransaction //事务类。目前由于ESQL仅提供查询的命令,没有提供对Insert、Update、Delete等的支持。所以,我觉得目前这个类基本没有用,(不可能我做查询还使用事务吧!)。

20、事务的支持

代码
using(cms_dbEntities content=new cms_dbEntities())
{
content.Connection.Open();
using(var trans=content.Connection.BeginTransaction(IsolationLevel.Serializable))
{
try
{
int i = Convert.ToInt32(textBox1.Text);
IQueryable
<lxp_content> select = from a in content.lxp_content
where a.C_id == i
select a;
IQueryable
<lxp_content> select1 = from b in content.lxp_content
where b.C_id == i + 1
select b;

foreach (var s in select)
{
content.DeleteObject(s);
}
foreach (var s in select1)
{
content.DeleteObject(s);
}
content.SaveChanges();
trans.Commit();
button2_Click(sender, e);
}
catch
{
trans.Rollback();
button2_Click(sender, e);
}
}
}
}

private void button4_Click(object sender, EventArgs e)
{
cms_dbEntities content
= new cms_dbEntities();
cms_dbEntities content2
= new cms_dbEntities();
IQueryable
<lxp_content> select = from a in content.lxp_content
where a.C_id == 60
select a;
IQueryable
<lxp_content> select2 = from b in content2.lxp_content
where b.C_id == 60
select b;
foreach (var a in select2)
{
a.C_hits
= a.C_hits + 10;
}
foreach (var s in select)
{
s.C_hits
= s.C_hits + 100;
}
// MessageBox.Show(content2);
content2.SaveChanges();
try
{
content.Refresh(RefreshMode.StoreWins,select);
content.SaveChanges();
}
catch (OptimisticConcurrencyException ex)
{

return;
}
}

 

 

21、对存储过程的支持
目前,EF对存储过程的支持并不完善。存在以下问题:

l        EF不支持存储过程返回多表联合查询的结果集。

l        EF仅支持返回返回某个表的全部字段,以便转换成对应的实体。无法支持返回部分字段的情况。

l        虽然可以正常导入返回标量值的存储过程,但是却没有为我们自动生成相应的实体.cs代码,我们还是无法在代码中直接调用或使用标量存储过程

l        EF不能直接支持存储过程中Output类型的参数。
选中对应的实体,添加函数导入,后选中建立的存储过程
调用时
 

using (cms_dbEntities content = new cms_dbEntities())
{
var ccgc
= content.ccgc(1);
}

 

 

同时存储过程中可以使用插入、删除、添加操作。传入对象可以为一个对象

22、MergeOption.NoTracking

当我们只需要读取某些数据而不需要删除、更新的时候,可以指定使用MergeOption.NoTracking的方式来执行只读查询(EF默认的方式是AppendOnly)。当指定使用NoTracking来进行只读查询时,与实体相关的引用实体不会被返回,它们会被自动设置为null。因此,使用NoTracking可以提升查询的性能。示例代码如下:

代码
[Test]



public void NoTrackingTest()



{



using (var db = new NorthwindEntities1())



{



//针对Customers查询将使用MergeOption.NoTracking



db.Customers.MergeOption
= MergeOption.NoTracking;



var cust
= db.Customers.Where(c => c.City == "London");



foreach (var c in cust)



Console.WriteLine(c.CustomerID);







//也可以这样写



//var cust1 = ((ObjectQuery<Customers>)cust).Execute(MergeOption.NoTracking);







//Esql写法



//string esql = "select value c from customers as c where c.CustomerID='ALFKI'";



//db.CreateQuery<Customers>(esql).Execute(MergeOption.NoTracking).FirstOrDefault();







}



}

 

 

复制代码GetObjectByKey/First

23、GetObjectByKey:

在EF中,使用GetObjectByKey方法获取数据时,它首先会查询是否有缓存,如果有缓存则从缓存中返回需要的实体。如果没有则查询数据库,返回需要的实体,并添加在缓存中以便下次使用。

First: 总从数据库中提取需要的实体。

因此,我们应在合适的地方选择GetObjectByKey方法来获取数据,以减少对数据库的访问提升性能。示例代码如下:

代码
[Test]



public void GetByKeyTest()



{



using (var db = new NorthwindEntities1())



{



//从数据库中提取数据



var cst
= db.Customers.First(c => c.CustomerID == "ALFKI");



Console.WriteLine(cst.CustomerID);







//将从缓存中提取数据



EntityKey key
= new EntityKey("NorthwindEntities1.Customers", "CustomerID", "ALFKI");



var cst1
= db.GetObjectByKey(key) as Customers;



Console.WriteLine(cst1.CustomerID);











}



}

 

 

复制代码此外,需要注意的是如果GetObjectByKey没有获取到符合条件的数据,那么它会抛异常。为了避免此情况发生,在有可能出现异常的地方,我们应该使用TryGetObjectByKey方法。TryGetObjectByKey方法获取数据的方式和GetObjectByKey类似,只是当没有取到符合条件的数据时,TryGetObjectByKey会返回null而不是抛异常。示例代码如下:

代码
[Test]



public void TryGetByKeyTest()



{



using (var db = new NorthwindEntities1())



{







//没有符合条件的数据会有异常抛出



EntityKey key
= new EntityKey("NorthwindEntities1.Customers", "CustomerID", "♂风车车.Net");



var cst
= db.GetObjectByKey(key) as Customers;



Console.WriteLine(cst.CustomerID);







//没有符合条件的数据会有返回null



EntityKey key1
= new EntityKey("NorthwindEntities1.Customers", "CustomerID", "♂风车车.Net");



Object cst1
= null;



db.TryGetObjectByKey(key1,
out cst1);



if (cst1 != null)



Console.WriteLine(((Customers)cst1).CustomerID);







}



}

 

 

24、复制代码First /FirstOrDefault

First: 当我们使用First来获取数据,如果没有符合条件的数据,那么我们的代码将会抛出异常。

FirstOrDefault: 当我们使用FirstOrDefault来获取的数据,如果没有符合条件的数据,那么它将返回null。

显然,对于一个良好的代码,是对可以预见的异常进行处理,而不是等它自己抛出来。示例代码如下:

代码
[Test]



public void FirstTest()



{



using (var db = new NorthwindEntities1())



{







//抛异常的代码



var cst
= db.Customers.First(c => c.CustomerID == "♂风车车.Net");



Console.WriteLine(cst.CustomerID);
//此处将出抛异常







//推荐的使用如下代码:



var cst1
= db.Customers.FirstOrDefault(c => c.CustomerID == "♂风车车.Net");



if (cst1 != null)



Console.WriteLine(cst1.CustomerID);



}



}

 

 

25、延迟加载/Include

EF不支持实体的部分属性延迟加载,但它支持实体关系的延迟加载。默认情况,实体的关系是不会加载。如下代码:

代码
[Test]



public void IncludeTest()



{



using (var db = new NorthwindEntities1())



{



var csts
= db.Customers;



foreach (var c in csts)



{



Console.WriteLine(c.CustomerID);



foreach (var o in c.Orders)



Console.WriteLine(
" " + o.OrderID);



}



}



}

 

 

复制代码上述代码中,因为Orders没有被加载,所以在输出Orders的时候,是不会有任何输出的。

当我们需要加载某些关联的关系时,可是用Include方法,如下代码所示:

代码
[Test]



public void IncludeTest()



{



using (var db = new NorthwindEntities1())



{



var csts
= db.Customers.Include("Orders");



foreach (var c in csts)



{



Console.WriteLine(c.CustomerID);



foreach (var o in c.Orders)



Console.WriteLine(
" " + o.OrderID);



}



}



}

 

 

复制代码上述代码中,Customers关联的Orders将被加载。


26、CompiledQuery

提供对查询的编译和缓存以供重新使用。当相同的查询需要执行很多遍的时候,那么我们可以使用ComplieQuery将查询的语句进行编译以便下次使用,这样可以免去对同一语句的多次处理,从而改善性能。

示例代码如下:

代码
[Test]



public void ComplieTest()



{



using (var db = new NorthwindEntities1())



{



//对查询进行编译



var customer
= CompiledQuery.Compile<NorthwindEntities1, IQueryable<Customers>>(



(database)
=> database.Customers.Where(c => c.City == "London"));







//执行20次相同的查询



for (int i = 0; i < 20; i++)



{



DateTime dt
= System.DateTime.Now;



foreach (var c in customer(db))



Console.WriteLine(c.CustomerID);



Console.WriteLine(DateTime.Now.Subtract(dt).TotalMilliseconds);



Console.WriteLine(
"---------------------------------------------------");



}







}



}

 

 

最后如果要实现自定义实体,则可以修改edmx文件
如:在实体中包含复杂数据类型,手动添加存储进程,添加带Output参数类型的存储过程,

posted on 2011-01-10 11:32  叩亦杰  阅读(3913)  评论(6编辑  收藏  举报