LINQ to SQL语句(25)之继承

来源:互联网 发布:郑州网络电视台直播 编辑:程序博客网 时间:2024/04/29 17:44

http://www.prg-cn.com/article-4424-1.html

继承支持

LINQ to SQL 支持单表映射,其整个继承层次结构存储在单个数据库表中。该表包含整个层次结构的所有可能数据列的平展联合。(联合是 将两个表组合成一个表的结果,组合后的表包含任一原始表中存在的行。)每行 中不适用于该行所表示的实例类型的列为 null。

单表映射策略是最简单 的继承表示形式,为许多不同类别的查询提供了良好的性能特征,如果我们要在 LINQ to SQL 中实现这种映射,必须在继承层次结构的根类中指定属性 (Attribute) 和属性 (Attribute) 的属性 (Property)。我们还可以使用O/R设 计器来映射继承层次结构,它自动生成了代码。

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

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

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

根类添加TableAttribute属性。

为层次结构中的每个 类添加InheritanceMappingAttribute属性,同样是添加到根类中。每个 InheritanceMappingAttribute属性,定义一个Code属性和一个Type属性。Code 属性的值显示在数据库表的IsDiscriminator列中,用来指示该行数据所属的类 或子类。Type属性值指定键值所表示的类或子类。

仅在其中一个 InheritanceMappingAttribute属性上,添加一个IsDefault属性用来在数据库表 中的鉴别器值在继承映射中不与任何Code值匹配时指定回退映射。

为 ColumnAttribute属性添加一个IsDiscriminator属性来表示这是保存Code值的列 。

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

  1. [Table(Name = "dbo.Contacts")]
  2. [InheritanceMapping(Code = "Unknown", Type = typeof (Contact),
  3.           IsDefault = true)]
  4. [InheritanceMapping(Code = "Employee", Type = typeof (EmployeeContact))]
  5. [InheritanceMapping(Code = "Supplier", Type = typeof(SupplierContact))]
  6. [InheritanceMapping(Code = "Customer", Type = typeof (CustomerContact))]
  7. [InheritanceMapping(Code = "Shipper", Type = typeof(ShipperContact))]
  8. public partial class Contact :
  9. INotifyPropertyChanging, INotifyPropertyChanged
  10. {
  11.   [Column(Storage = "_ContactID",IsPrimaryKey = true,
  12.   IsDbGenerated = true)]
  13.   public int ContactID{ }
  14.   [Column(Storage = "_ContactType",IsDiscriminator = true)]
  15.   public string ContactType{ }
  16. }
  17. public abstract partial class FullContact : Contact{ }
  18. public partial class EmployeeContact : FullContact{ }
  19. public partial class SupplierContact : FullContact{ }
  20. public partial class CustomerContact : FullContact{ }
  21. public partial class ShipperContact : Contact{ }
复制代码

1.一般形式

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

  1. var cons = from c in db.Contacts
  2.        select c;
  3. foreach (var con in cons) {
  4.    Console.WriteLine("Company name: {0}", con.CompanyName);
  5.   Console.WriteLine("Phone: {0}", con.Phone);
  6.    Console.WriteLine("This is a {0}", con.GetType());
  7. }
复制代码

2.OfType形式

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

  1. var cons = from c in db.Contacts.OfType<CustomerContact>()
  2.       select c;
复制代码

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

  1. SELECT [t0].[ContactType], [t0].[ContactName], [t0].[ContactTitle],
  2. [t0].[Address],[t0].[City], [t0].[Region], [t0].[PostalCode],
  3. [t0].[Country], [t0].[Fax],[t0].[ContactID], [t0].[CompanyName],
  4. [t0].[Phone] FROM [dbo].[Contacts] AS [t0]
  5. WHERE ([t0]. [ContactType] = @p0) AND ([t0].[ContactType] IS NOT NULL)
  6. -- @p0: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Customer]
复制代码

3.IS形式

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

  1. var cons = from c in db.Contacts
  2.       where c is ShipperContact
  3.       select c;
复制代码

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

  1. SELECT [t0].[ContactType], [t0].[ContactID], [t0]. [CompanyName],
  2. [t0].[Phone],[t0].[HomePage], [t0]. [ContactName],
  3. [t0].[ContactTitle], [t0].[Address], [t0]. [City],
  4. [t0].[Region], [t0].[PostalCode], [t0].[Country],
  5. [t0].[Fax],[t0].[PhotoPath], [t0].[Photo], [t0].[Extension]
  6. FROM [dbo].[Contacts] AS [t0] WHERE ([t0].[ContactType] = @p0)
  7. AND ([t0].[ContactType] IS NOT NULL)
  8. -- @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
复制代码

4.AS形式

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

  1. var cons = from c in db.Contacts
  2.       select c as FullContact;
复制代码

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

  1. SELECT [t0]. [ContactType], [t0].[HomePage], [t0].[ContactName],
  2. [t0]. [ContactTitle],[t0].[Address], [t0].[City],
  3. [t0].[Region], [t0]. [PostalCode], [t0].[Country],
  4. [t0].[Fax], [t0].[ContactID], [t0].[CompanyName],
  5. [t0].[Phone], [t0].[PhotoPath],[t0].[Photo], [t0].[Extension]
  6. FROM [dbo].[Contacts] AS [t0]
复制代码

5.Cast形式

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

  1. var cons = from c in db.Contacts
  2.       where c.ContactType == "Customer" &&
  3.             ((CustomerContact)c).City == "London"
  4.        select c;
复制代码

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

  1. SELECT [t0].[ContactType], [t0].[ContactID], [t0]. [CompanyName],
  2. [t0].[Phone], [t0].[HomePage],[t0]. [ContactName],
  3. [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
  4. [t0].[PostalCode], [t0].[Country], [t0].[Fax], [t0].[PhotoPath],
  5. [t0].[Photo], [t0].[Extension]FROM [dbo]. [Contacts] AS [t0]
  6. WHERE ([t0].[ContactType] = @p0) AND ([t0]. [City] = @p1)
  7. -- @p0: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Customer]
  8. -- @p1: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [London]
复制代码

6.UseAsDefault形式

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

  1. //插入一条数据默认使用正常的映射关系
  2. Contact contact = new Contact()
  3. {
  4.   ContactType = null,
  5.   CompanyName = "Unknown Company",
  6.    Phone = "333-444-5555"
  7. };
  8. db.Contacts.InsertOnSubmit(contact);
  9. db.SubmitChanges();
  10. //查询一条数据默认使用继承映射关系
  11. var con =
  12.   (from c in db.Contacts
  13.    where c.CompanyName == "Unknown Company" &&
  14.               c.Phone == "333-444-5555"
  15.    select c).First();
复制代码

生 成SQL语句如下:

  1. INSERT INTO [dbo].[Contacts] ([ContactType], [CompanyName],
  2. [Phone]) VALUES (@p0, @p1, @p2)
  3. SELECT TOP (1) [t0].[ContactType], [t0].[ContactID],
  4. [t0]. [CompanyName], [t0].[Phone],[t0].[HomePage],
  5. [t0].[ContactName], [t0].[ContactTitle], [t0].[Address],
  6. [t0].[City],[t0].[Region], [t0].[PostalCode], [t0].[Country],
  7. [t0].[Fax], [t0].[PhotoPath], [t0].[Photo], [t0].[Extension]
  8. FROM [dbo].[Contacts] AS [t0]
  9. WHERE ([t0].[CompanyName] = @p0) AND ([t0].[Phone] = @p1)
  10. -- @p0: Input NVarChar (Size = 15; Prec = 0; Scale = 0)
  11.   [Unknown Company]
  12. -- @p1: Input NVarChar (Size = 12; Prec = 0; Scale = 0)
  13.   [333-444-5555]
复制代码

7.插入新的记录

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

  1. //
复制代码

1.在插 入之前查询一下,没有数据

  1. var ShipperContacts =
  2.   from sc in db.Contacts.OfType<ShipperContact>()
  3.   where sc.CompanyName == "Northwind Shipper"
  4.   select sc;
  5. //
复制代码

2.插入数据

  1. ShipperContact nsc = new ShipperContact()
  2. {
  3.   CompanyName = "Northwind Shipper",
  4.   Phone = "(123)-456-7890"
  5. };
  6. db.Contacts.InsertOnSubmit(nsc);
  7. db.SubmitChanges();
  8. //
复制代码

3.查询数据,有一条记录

  1. ShipperContacts =
  2.   from sc in db.Contacts.OfType<ShipperContact>()
  3.    where sc.CompanyName == "Northwind Shipper"
  4.   select sc;
  5. //
复制代码

4.删除记录

  1. db.Contacts.DeleteOnSubmit (nsc);
  2. db.SubmitChanges();
复制代码

生成SQL语句如下:

  1. SELECT COUNT(*) AS [value] FROM [dbo].[Contacts] AS [t0]
  2. WHERE ([t0].[CompanyName] = @p0) AND ([t0].[ContactType] = @p1)
  3. AND ([t0].[ContactType] IS NOT NULL)
  4. -- @p0: Input NVarChar [Northwind Shipper]
  5. -- @p1: Input NVarChar [Shipper]
  6. INSERT INTO [dbo].[Contacts]([ContactType], [CompanyName], [Phone])
  7. VALUES (@p0, @p1, @p2)
  8. -- @p0: Input NVarChar [Shipper]
  9. -- @p1: Input NVarChar [Northwind Shipper]
  10. -- @p2: Input NVarChar [(123)-456-7890]
  11. SELECT COUNT(*) AS [value] FROM [dbo].[Contacts] AS [t0]
  12. WHERE ([t0].[CompanyName] = @p0) AND ([t0].[ContactType] = @p1)
  13. AND ([t0].[ContactType] IS NOT NULL)
  14. -- @p0: Input NVarChar [Northwind Shipper]
  15. -- @p1: Input NVarChar [Shipper]
  16. DELETE FROM [dbo].[Contacts] WHERE ([ContactID] = @p0) AND
  17. ([ContactType] = @p1) AND ([CompanyName] = @p2) AND ([Phone] = @p3)
  18. -- @p0: Input Int [159]
  19. -- @p1: Input NVarChar [Shipper]
  20. -- @p2: Input NVarChar [Northwind Shipper]
  21. -- @p3: Input NVarChar [(123)-456-7890]
  22. -- @p4: Input NVarChar [Unknown]
  23. -- @p5: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Supplier]
  24. -- @p6: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Shipper]
  25. -- @p7: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Employee]
  26. -- @p8: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Customer]
复制代码