使用 Fluent NHibernate 将单个字段映射到多个表

发布于 2024-08-14 09:35:36 字数 1516 浏览 5 评论 0原文

问题:有没有办法根据上下文将单个外键映射到多个互斥表?

背景...

在我的具体示例中,我有以下域图,代表可以针对车辆财产的保险索赔:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柠北森屋 2024-08-21 09:35:36

就我个人而言,我不会接受你的设计。相反,我会分别创建 Claim 类的子类、VehicleClaimPropertyClaim

public class VehicleClaim : Claim
{
  public virtual Vehicle Vehicle { get; set; }
}

然后更改映射以使用 InvolvedPartyContext 列作为鉴别器(NHibernate 使用该列来确定该行代表哪个类),并为每个子类创建子类映射。

public class ClaimMap : ClassMap<Claim>
{
  public ClaimMap()
  {
    Id(x => x.Id);
    DiscriminateSubClassesOnColumn("InvolvedPartyContext");
  }
}

public class VehicleClaimMap : SubclassMap<VehicleClaim>
{
  public VehicleClaimMap()
  {
    DiscriminatorValue(1);
    References(x => x.Vehicle);
  }
}

如果您确实想使用现有的东西来运行,您应该查看任何映射;关于它们的文档并不多,但您可以使用 ReferencesAny 方法。

Personally, I wouldn't go with the design you have. Instead I'd create subclasses of your Claim class, VehicleClaim and PropertyClaim respectively.

public class VehicleClaim : Claim
{
  public virtual Vehicle Vehicle { get; set; }
}

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.

public class ClaimMap : ClassMap<Claim>
{
  public ClaimMap()
  {
    Id(x => x.Id);
    DiscriminateSubClassesOnColumn("InvolvedPartyContext");
  }
}

public class VehicleClaimMap : SubclassMap<VehicleClaim>
{
  public VehicleClaimMap()
  {
    DiscriminatorValue(1);
    References(x => x.Vehicle);
  }
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文