Linq To Sql(以下简称LS)从一降世似乎就是个问题宝宝。批更新问题, Like问题,RTM之前的"BUG"(select new不能显式创建实体)等等接踵而至,很多时候我们不得不回到SqlCommand去来"扩展"LS,不巧的是,LS留给程序员的灵活性很有限,我们的Extension总是有不尽完美的地方,在自我扩展的同时我更多的是期待Entity Framework正式Release时候能解决这些问题,至少是能够带给我们更多的灵活性。今天我要说的是LS中的继承问题,先看实体关系:
简要说明一下:Order实体和Supplier实体对应数据库中的表,而OrderInfo实体很明显是连接了两个实体的“视图”。这样的应用场景很常见,我可能需要OrderInfo去填充一个Grid,而又需要在OrderInfo被修改之后提交回数据库, 很显然OrderInfo必须是一个实际类型而非匿名类型。有人会问为什么不用视图去生成OrderInfo实体,原因很简单,视图是无法提交修改的,为了让能够OrderInfo直接提交回数据库更好的做法是让他继承于Order,于是乎,很自然的想到OrderInfo的代码是这样:
[Table(Name = "dbo.Order")]
public class OrderInfo : Order
{
private string _SupplierName;
public OrderInfo()
{
}
public string SupplierName
{
get
{
return this._SupplierName;
}
set
{
if ((this._SupplierName != value))
{
this._SupplierName = value;
}
}
}
}
那么查询可以是这样的:
using (DataClasses1DataContext context = new DataClasses1DataContext())
{
OrderInfo[] infos = from o in context.Orders
join s in context.Suppliers on o.SupplierId equals s.SupplierId
select new OrderInfo
{
OrderId = o.OrderId,
SupplierId = o.SupplierId,
SupplierName = s.SupplierName
};
return infos;
} 不好意思,RTM之后这个语句运行时候会出错,具体的可以参看JeffreyZhao的文章,里面给了一个扩展可以绕过这先限制,但是遗憾的是在这个问题上那个扩展一样失败,原因是OrderInfo从基类(Order)继承下来的属性不属于OrderInfo的映射,我很自然的想到用LS继承方式,那么代码可以这样:
[System.Data.Linq.Mapping.InheritanceMapping(Code = "Order", Type = typeof(Order), IsDefault = true)]
[System.Data.Linq.Mapping.InheritanceMapping(Code = "OrderInfo", Type = typeof(OrderInfo))]
public partial class Order
{
[Column(IsDiscriminator = true, IsDbGenerated = true, AutoSync = AutoSync.Never)]
public string Type { get; set; }
}
同时去掉OrderInfo类上的TableAttribute,注意,上面的Order类代码是放在LS设计器生成的代码之外的运用了局部类特性,不好意思这样的代码过不去,LS的继承方式必须要有个叫做鉴别器列的东西,那么我们还要向Order类添加一个属性:
[Column(IsDiscriminator = true)]
public string Type { get; set; } 很显然,这样的属性必定导致我们提交数据失败,因为数据库中根本没有这个列,那么我们在做一点手脚:
[Column(IsDiscriminator = true, IsDbGenerated = true, AutoSync = AutoSync.Never)]
public string Type { get; set; }
似乎很阴险,骗过LS,让他认为Type列示个自动生成列,这样提交时候就不会向这个列插入数据了,同时把AutoSync属性置为AutoSync.Never,这样做是因为LS在做插入或者更新操作时候会把这个列的值同步到实体,算是LS应对并发的一点自动化操作吧,如果他同步属性值那同样会由于数据库中没这个列而失败,因此我们禁止这样的同步。
本文来自于 - Sharping''s Technique Claver - 博客园
更详细信息,请点击查看原文。