当前位置:首页 > LINQ体验(18)——LINQ to SQL语句之视图和继承支持

LINQ体验(18)——LINQ to SQL语句之视图和继承支持

点击次数:1011  更新日期:2010-12-30
\n

视图


\n

我们使用视图和使用数据表类似,只需将视图从“服务器资源管理器/数据库资源管理器”拖动到O/R 设计器上,自动可以创建基于这些视图的实体类。我们可以同操作数据表一样来操作视图了。这里注意:O/R 设计器是一个简单的对象关系映射器,因为它仅支持 1:1 映射关系。换句话说,实体类与数据库表或视图之间只能具有 1:1 映射关系。不支持复杂映射(例如,将一个实体类映射到多个表)。但是,可以将一个实体类映射到一个联接多个相关表的视图。 下面使用NORTHWND数据库中自带的Invoices、Quarterly Orders两个视图为例,写出两个范例。


\n

查询:匿名类型形式


\n

我们使用下面代码来查询出ShipCity 在London的发票。

var q =
\n from i in db.Invoices
\n where i.ShipCity == “London”
\n select new {i.OrderID, i.ProductName, i.Quantity, i.CustomerName};

\n

这里,生成的SQL语句同使用数据表类似:

SELECT [t0].[OrderID], [t0].[ProductName], [t0].[Quantity], [t0].[CustomerName]
\nFROM [dbo].[Invoices] AS [t0] WHERE [t0].[ShipCity] = @p0
\n– @p0: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [London]

\n

查询:主键映射形式


\n

下例查询出每季的订单。

var q =
\n from qo in db.Quarterly_Orders
\n select qo;

\n

生成SQL语句为:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[City], [t0].[Country]
\nFROM [dbo].[Quarterly Orders] AS [t0]

\n

继承支持


\n

LINQ to SQL 支持单表映射,其整个继承层次结构存储在单个数据库表中。该表包含整个层次结构的所有可能数据列的平展联合。(联合是将两个表组合成一个表的结果,组合后的表包含任一原始表中存在的行。)每行中不适用于该行所表示的实例类型的列为 null。
单表映射策略是最简单的继承表示形式,为许多不同类别的查询提供了良好的性能特征,如果我们要在 LINQ to SQL 中实现这种映射,必须在继承层次结构的根类中指定属性 (Attribute) 和属性 (Attribute) 的属性 (Property)。我们还可以使用O/R设计器来映射继承层次结构,它自动生成了代码。


\n

下面为了演示下面的几个例子,我们在O/R设计器内设计如下图所示的类及其继承关系。


\n

继承


\n

我们学习的时候还是看看其生成的代码吧!


\n

具体设置映射继承层次结构有如下几步:


\n

    \n
  1. 根类添加TableAttribute属性。
    \n
  2. 为层次结构中的每个类添加InheritanceMappingAttribute属性,同样是添加到根类中。每个 InheritanceMappingAttribute属性,定义一个Code属性和一个Type属性。Code属性的值显示在数据库表的IsDiscriminator列中,用来指示该行数据所属的类或子类。Type属性值指定键值所表示的类或子类。
    \n
  3. 仅在其中一个InheritanceMappingAttribute属性上,添加一个IsDefault属性用来在数据库表中的鉴别器值在继承映射中不与任何Code值匹配时指定回退映射。
    \n
  4. 为ColumnAttribute属性添加一个IsDiscriminator属性来表示这是保存Code值的列。

\n

下面是这张图生成的代码的框架(由于生成的代码太多,我删除了很多“枝叶”,仅仅保留了主要的框架用于指出其实质的东西):

[Table(Name = "dbo.Contacts")]
\n[InheritanceMapping(Code = "Unknown", Type = typeof(Contact), IsDefault = true)]
\n[InheritanceMapping(Code = "Employee", Type = typeof(EmployeeContact))]
\n[InheritanceMapping(Code = "Supplier", Type = typeof(SupplierContact))]
\n[InheritanceMapping(Code = "Customer", Type = typeof(CustomerContact))]
\n[InheritanceMapping(Code = "Shipper", Type = typeof(ShipperContact))]
\npublic partial class Contact : INotifyPropertyChanging, INotifyPropertyChanged
\n{
\n [Column(Storage = "_ContactID",IsPrimaryKey = true, IsDbGenerated = true)]
\n public int ContactID{ }
\n [Column(Storage = "_ContactType",IsDiscriminator = true)]
\n public string ContactType{ }
\n}
\npublic abstract partial class FullContact : Contact{ }
\npublic partial class EmployeeContact : FullContact{ }
\npublic partial class SupplierContact : FullContact{ }
\npublic partial class CustomerContact : FullContact{ }
\npublic partial class ShipperContact : Contact{ }

\n

1.一般形式


\n

日常我们经常写的形式,对单表查询。

var cons = from c in db.Contacts
\n select c;
\nforeach (var con in cons) {
\n Console.WriteLine(“Company name: {0}”, con.CompanyName);
\n Console.WriteLine(“Phone: {0}”, con.Phone);
\n Console.WriteLine(“This is a {0}”, con.GetType());
\n}

\n

2.OfType形式


\n

这里我仅仅让其返回顾客的联系方式。

var cons = from c in db.Contacts.OfType()
\n select c;

\n

初步学习,我们还是看看生成的SQL语句,这样容易理解。在SQL语句中查询了ContactType为Customer的联系方式。

SELECT [t0].[ContactType], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address],
\n[t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Fax],
\n[t0].[ContactID], [t0].[CompanyName], [t0].[Phone] FROM [dbo].[Contacts] AS [t0]
\nWHERE ([t0].[ContactType] = @p0) AND ([t0].[ContactType] IS NOT NULL)
\n– @p0: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Customer]

\n

3.IS形式


\n

这个例子查找一下发货人的联系方式。

var cons = from c in db.Contacts
\n where c is ShipperContact
\n select c;

\n

生成的SQL语句如下:查询了ContactType为Shipper的联系方式。大致一看好像很上面的一样,其实这里查询出来的列多了很多。实际上是Contacts表的全部字段。

SELECT [t0].[ContactType], [t0].[ContactID], [t0].[CompanyName], [t0].[Phone],
\n[t0].[HomePage], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address],
\n[t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Fax],
\n[t0].[PhotoPath], [t0].[Photo], [t0].[Extension] FROM [dbo].[Contacts] AS [t0]
\nWHERE ([t0].[ContactType] = @p0) AND ([t0].[ContactType] IS NOT NULL)
\n– @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]

\n

4.AS形式


\n

这个例子就通吃了,全部查找了一番。

var cons = from c in db.Contacts
\n select c as FullContact;

\n

生成SQL语句如下:查询整个Contacts表。

SELECT [t0].[ContactType], [t0].[HomePage], [t0].[ContactName], [t0].[ContactTitle],
\n[t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country],
\n[t0].[Fax], [t0].[ContactID], [t0].[CompanyName], [t0].[Phone], [t0].[PhotoPath],
\n[t0].[Photo], [t0].[Extension] FROM [dbo].[Contacts] AS [t0]

\n

5.Cast形式


\n

使用Case形式查找出在伦敦的顾客的联系方式。

var cons = from c in db.Contacts
\n where c.ContactType == “Customer” &&
\n ((CustomerContact)c).City == “London”
\n select c;

\n

生成SQL语句如下,自己可以看懂了。

SELECT [t0].[ContactType], [t0].[ContactID], [t0].[CompanyName], [t0].[Phone], [t0].[HomePage],
\n[t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
\n[t0].[PostalCode], [t0].[Country], [t0].[Fax], [t0].[PhotoPath], [t0].[Photo], [t0].[Extension]
\nFROM [dbo].[Contacts] AS [t0] WHERE ([t0].[ContactType] = @p0) AND ([t0].[City] = @p1)
\n– @p0: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Customer]
\n– @p1: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [London]

\n

6.UseAsDefault形式


\n

当插入一条记录时,使用默认的映射关系了,但是在查询时,使用继承的关系了。具体看看生成的SQL语句就直截了当了。

//插入一条数据默认使用正常的映射关系
\nContact contact = new Contact() { ContactType = null,
\n CompanyName = “Unknown Company”,
\n Phone = “333-444-5555″ };
\ndb.Contacts.InsertOnSubmit(contact);
\ndb.SubmitChanges();
\n//查询一条数据默认使用继承映射关系
\nvar con = (from c in db.Contacts
\n where c.CompanyName == “Unknown Company” &&
\n c.Phone == “333-444-5555″
\n select c).First();

\n

生成SQL语句如下:

INSERT INTO [dbo].[Contacts]([ContactType], [CompanyName], [Phone])
\nVALUES (@p0, @p1, @p2)
\nSELECT TOP (1) [t0].[ContactType], [t0].[ContactID], [t0].[CompanyName], [t0].[Phone],
\n[t0].[HomePage], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City],
\n[t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Fax], [t0].[PhotoPath],
\n[t0].[Photo], [t0].[Extension] FROM [dbo].[Contacts] AS [t0]
\nWHERE ([t0].[CompanyName] = @p0) AND ([t0].[Phone] = @p1)
\n– @p0: Input NVarChar (Size = 15; Prec = 0; Scale = 0) [Unknown Company]
\n– @p1: Input NVarChar (Size = 12; Prec = 0; Scale = 0) [333-444-5555]

\n

7.插入新的记录


\n

这个例子说明如何插入发货人的联系方式的一条记录。

//1.在插入之前查询一下,没有数据
\nvar ShipperContacts = from sc in db.Contacts.OfType()
\n where sc.CompanyName == “Northwind Shipper”
\n select sc;
\n//2.插入数据
\nShipperContact nsc = new ShipperContact() {
\n CompanyName = “Northwind Shipper”, Phone = “(123)-456-7890″ };
\ndb.Contacts.InsertOnSubmit(nsc);
\ndb.SubmitChanges();
\n//3.查询数据,有一条记录
\nShipperContacts = from sc in db.Contacts.OfType()
\n where sc.CompanyName == “Northwind Shipper”
\n select sc;
\n//4.删除记录
\ndb.Contacts.DeleteOnSubmit(nsc);
\ndb.SubmitChanges();

\n

生成SQL语句如下:

SELECT COUNT(*) AS [value] FROM [dbo].[Contacts] AS [t0]
\nWHERE ([t0].[CompanyName] = @p0) AND ([t0].[ContactType] = @p1)
\nAND ([t0].[ContactType] IS NOT NULL)
\n– @p0: Input NVarChar (Size = 17; Prec = 0; Scale = 0) [Northwind Shipper]
\n– @p1: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
\nINSERT INTO [dbo].[Contacts]([ContactType], [CompanyName], [Phone])
\nVALUES (@p0, @p1, @p2)
\n– @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
\n– @p1: Input NVarChar (Size = 17; Prec = 0; Scale = 0) [Northwind Shipper]
\n– @p2: Input NVarChar (Size = 14; Prec = 0; Scale = 0) [(123)-456-7890]
\nSELECT COUNT(*) AS [value] FROM [dbo].[Contacts] AS [t0]
\nWHERE ([t0].[CompanyName] = @p0) AND ([t0].[ContactType] = @p1)
\nAND ([t0].[ContactType] IS NOT NULL)
\n– @p0: Input NVarChar (Size = 17; Prec = 0; Scale = 0) [Northwind Shipper]
\n– @p1: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
\nDELETE FROM [dbo].[Contacts] WHERE ([ContactID] = @p0) AND
\n([ContactType] = @p1) AND ([CompanyName] = @p2) AND ([Phone] = @p3)
\n– @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [159]
\n– @p1: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
\n– @p2: Input NVarChar (Size = 17; Prec = 0; Scale = 0) [Northwind Shipper]
\n– @p3: Input NVarChar (Size = 14; Prec = 0; Scale = 0) [(123)-456-7890]
\n– @p4: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Unknown]
\n– @p5: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Supplier]
\n– @p6: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
\n– @p7: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Employee]
\n– @p8: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Customer]

\n

本系列链接:LINQ体验系列文章导航


\n

作者:李永京(YJingLee’s Blog)
出处:http://lyj.cnblogs.com

\n