[LINQ] 深入SQL Entity与EntityRef<T>内部
2011-11-28 13:09
323 查看
引言
最近在学习LINQ,已经逐步深入到LINQ to SQL和LINQ to Entity的部分。但是对SQL Entity专题中的EntityRef<T>很是迷惑,始终未能理解它是如何从数据库的1:1关系转变为C#中两个对象的相互引用的,于是有了这段摸索。阅读本文,需要对SQL Entity的内部结构有一定程度的了解。
线索
问题源自于下面我自己写的这段旨在测试引用关系的代码,Customers与Orders是通过“LINQ to SQL类”(.dbml)的方式,从数据库生成的SQL Entity类。其中,测试用例的客户Thomas Hardy的CustomerID为AROUT。using (NorthwindDataContext db = new NorthwindDataContext())
{
db.Log = Console.Out;
Customers customer = db.Customers.Where(c => c.ContactName == "Thomas Hardy").SingleOrDefault();
Console.WriteLine("the customer {0} lives in {1}", customer.City);
Console.WriteLine("he gets {0} orders.", customer.Orders.Count);
Orders order = db.Orders.Where(o => o.CustomerID == "AROUT").FirstOrDefault();
Console.WriteLine("get the first order id is: {0}", order.OrderID);
Console.WriteLine(object.ReferenceEquals("is the reference equal? {0}", customer, order.Customers));
}
运行的结果
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactT
itle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Coun
try], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[ContactName] = @p0
-- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [Thomas Hardy]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
the customer Thomas Hardy lives in London
SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [
t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight], [t0].[Sh
ipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[ShipPosta
lCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[CustomerID] = @p0
-- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [AROUT]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
he gets 13 orders.
SELECT TOP (1) [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[Order
Date], [t0].[RequiredDate], [t0].[ShippedDate], [t0].[ShipVia], [t0].[Freight],
[t0].[ShipName], [t0].[ShipAddress], [t0].[ShipCity], [t0].[ShipRegion], [t0].[S
hipPostalCode], [t0].[ShipCountry]
FROM [dbo].[Orders] AS [t0]
WHERE [t0].[CustomerID] = @p0
-- @p0: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [AROUT]
-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
get the first order id is: 10355
is the reference equal? True
从结果看,对象customer与order在我们没有显式地建立彼此的引用的情况下,通过LINQ to SQL仍实现了完美的相互引用,从而使最后的引用比较得到了True的结果。
摸索过程
打断点+单步调试,这是深入Entity内部的简易方法。最后得出如下的一张流程图。从图中可以看出,
1. 子表对应的Entity对象并不会在父表Entity对象被填充时一并被构造并填充(除非显式地LoadWith)。EntitySet<T>与EntityRef<T>都是独立于作为其内部元素的Entity对象的数据结构。
2. 总是先生成SQL查询语句,随后才由LINQ构造并填充Entity对象。
3. attach/detach方法,是建立彼此引用的核心。
EntityRef<T>的结构
除了MSDN的帮助,我利用反射,获得了EntityRef<T>的结构图:利用调试工具,还能看见其内部的私有成员:
到此,终于对LINQ to SQL Entity Class的数据加载,以及EntityRef<T>与EntitySet<T>的关系有了更深入的了解,心中的疑惑也终于有了一个答案。
转:/article/5246856.html
相关文章推荐
- Note On <Programming Entity Framework 2nd Edition> -01: How to Use LINQPad 4.5
- 无法从用法中推导出方法“System.Data.Linq.Table<MvcTest.Models.Dinner>.InsertAllOnSubmit<TSubEntity>(System.Colle
- 深入SQL Entity与EntityRef<T>内部
- 写一个MyList<T>的类,内部用T[]实现(不能使用系统的List<T>类),需要实现的接口如下:
- cassandra 学习之旅<三> 内部认证与授权
- JavaSE笔记之<访问权限控制深入>
- deleted entity passed to persist: [dcms.ebridge.market.entity.Reward#<null>]
- C#.Net:List<T>集合列表的Linq语句查询示例
- EBS OAF开发中的Java 实体对象(Entity Object)<三>
- org.hibernate.ObjectDeletedException: deleted entity passed to persist: [xxx#<null>]
- Linq List<T>.Distinct() 去除对象重复
- <jsp:useBean />及相关动作深入理解
- <十>内部类
- 方法重载(overload)的例子分析(摘自<深入理解Java虚拟机>)
- <default-action-ref>的用法
- 深入了解FMDB<三>
- ArrayList、List<T>、HashSet<T>、LinkedList<T>各自优点和缺点,Dictionary<K,V>的内部存储数据方式有什么特殊的?
- CCSet(内部std::set实现 成员std::set<CCObject *> *m_pSet count addObject containsObject begin anyObject)
- JavaSE笔记之<多态深入理解>
- The Difference between <resource-ref> and <resource-env-ref>,the title should be long...