使用 Fluent NHibernate 将单个字段映射到多个表
问题:有没有办法根据上下文将单个外键映射到多个互斥表?
背景...
在我的具体示例中,我有以下域图,代表可以针对车辆或财产的保险索赔:
public enum InvolvedPartyContext
{
Vehicle = 1,
Property = 2
}
public class Claim
{
public virtual Guid Id { get; set; }
public virtual InvolvedPartyContext InvolvedPartyContext { get; set; }
public virtual Vehicle Vehicle { get; set; } // set if Context = Vehicle
public virtual Property Property { get; set; } // set if Context = Property
}
public class Vehicle { //... }
public class Property { //... }
SQL 如下所示(注意单个外键 InvolvedPartyId):
CREATE TABLE Claims (
Id uniqueidentifier NOT NULL,
InvolvedPartyContext int NOT NULL,
InvolvedPartyId uniqueidentifier NOT NULL
)
CREATE TABLE Vehicles (
Id uniqueidentifier NOT NULL,
Registration varchar(20) NOT NULL
)
CREATE TABLE Properties (
Id uniqueidentifier NOT NULL,
PostCode varchar(20) NOT NULL
)
声明的 Fluent NHibernate 映射文件:
public ClaimMap()
{
Id(x => x.Id);
Map(x => x.InvolvedPartyContext).CustomTypeIs(typeof(InvolvedPartyContext));
References(x => x.Vehicle, "InvolvedPartyId");
References(x => x.Property, "InvolvedPartyId");
}
这会抛出“此 SqlParameterCollection 的索引 {n} 无效,计数为 {m}”异常,因为同一字段 (InvolvedPartyId) 被映射两次。一个简单的修复方法是创建 VehicleId 和 PropertyId 字段,但在现实世界中存在更多上下文,因此这不是很灵活。
Question: is there a way to map a single foreign key to a number of mutually exclusive tables, based on a context?
Background...
In my specific example, I have the following domain graph, representing an insurance claim which can be against a vehicle or property:
public enum InvolvedPartyContext
{
Vehicle = 1,
Property = 2
}
public class Claim
{
public virtual Guid Id { get; set; }
public virtual InvolvedPartyContext InvolvedPartyContext { get; set; }
public virtual Vehicle Vehicle { get; set; } // set if Context = Vehicle
public virtual Property Property { get; set; } // set if Context = Property
}
public class Vehicle { //... }
public class Property { //... }
The SQL looks like this (notice the single foreign key InvolvedPartyId):
CREATE TABLE Claims (
Id uniqueidentifier NOT NULL,
InvolvedPartyContext int NOT NULL,
InvolvedPartyId uniqueidentifier NOT NULL
)
CREATE TABLE Vehicles (
Id uniqueidentifier NOT NULL,
Registration varchar(20) NOT NULL
)
CREATE TABLE Properties (
Id uniqueidentifier NOT NULL,
PostCode varchar(20) NOT NULL
)
The Fluent NHibernate mapping file for Claim:
public ClaimMap()
{
Id(x => x.Id);
Map(x => x.InvolvedPartyContext).CustomTypeIs(typeof(InvolvedPartyContext));
References(x => x.Vehicle, "InvolvedPartyId");
References(x => x.Property, "InvolvedPartyId");
}
This throws an "Invalid index {n} for this SqlParameterCollection with Count {m}" exception, since the same field (InvolvedPartyId) is mapped twice. A simple fix would be to create VehicleId and PropertyId fields, but in the real world there are many more contexts, so this isn't very flexible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
就我个人而言,我不会接受你的设计。相反,我会分别创建
Claim
类的子类、VehicleClaim
和PropertyClaim
。然后更改映射以使用
InvolvedPartyContext
列作为鉴别器(NHibernate 使用该列来确定该行代表哪个类),并为每个子类创建子类映射。如果您确实想使用现有的东西来运行,您应该查看任何映射;关于它们的文档并不多,但您可以使用
ReferencesAny
方法。Personally, I wouldn't go with the design you have. Instead I'd create subclasses of your
Claim
class,VehicleClaim
andPropertyClaim
respectively.Then change your mappings to use your
InvolvedPartyContext
column as a discriminator (the column which NHibernate uses to determine which class the row represents), and create subclass mappings for each subclass.If you really do want to run with what you've got, you should look into the any mappings; there isn't a lot of documentation on them, but you use the
ReferencesAny
method.