【问题标题】:Mapping one-to-one relationship with a wrong (brownfield) database schema使用错误的(棕地)数据库模式映射一对一关系
【发布时间】:2011-05-21 12:56:24
【问题描述】:

我必须在 NHibernate 中对这种关系进行建模(稍微简化代码以保持主题)——员工可以是客户经理(因此,它是可选的):

表员工(ID、编号、姓名) 表 EmployeeIsAccountManager (Number, MaxAllowedDiscount)

我在 EmployeeIsAccountManager 表中没有指向 Employee 表的 Id 外键,而是在 Employee 表中有一个 Number 列,它指向 EmployeeIsAccountManager 表中的 Number 列。

如何在 NHibernate 中映射它?我尝试在 EmployeeIsAccountManager 类映射上使用外部生成器,但如果我使用 Number 作为外部生成值,它会映射到 Employee 的 ID,它是 Id 而不是 Number。我为我的班级建模以使用组合:

public class Employee
{
   public virtual int Id { get; set; }
   public virtual short Number {get; set; }
   public virtual string Name {get; set; }
   public virtual AccountManager AccountManager { get; set; }
}

public class AccountManager
{
  public virtual short Number { get; set; } /*needed because of ID only?*/
  public virtual decimal MaxAllowedDiscount { get; set }
}   

我已经尝试了很多(一对一、多对一、外部生成器),但我不知道这是否可以使用 NHibernate 完成。顺便说一句:我可以更改类、映射等,但我不能更改表结构,因为它处于棕地状态(旧应用程序有 2+ 百万行代码,近 1000 个表单)。

感谢任何帮助,谢谢! 泰德

【问题讨论】:

  • 查找property-ref映射属性...

标签: nhibernate nhibernate-mapping brownfield


【解决方案1】:

你的问题让我想到了类继承,你可以将你的类 AccountManager 映射为 Employee 的子类,然后你就可以做你想做的事情,我已经为你测试了一个映射,但是当你设计的表way 不能解决您的需求,因为您在映射中必须注意两点:

  1. Employee 表中的 number 属性应该是 AccountManager 的一种独特的外键,以便用作外键,但即使这样它也不起作用,因为 NHibernate,当您尝试插入新的 Account Manager 时在 person 表中插入一条记录,然后将 person 的 id 分配给 AccountManager 的 number 列,这是您需要的休息时间。
  2. 出于同样的原因,将该关系映射为多对一并不起作用。 AccountManager 的 Number 属性是主键吗?是独特的? NHibernate 不能在没有主键的情况下工作,因此为了使这种关系正常工作,您必须将 AccountManager 的 Number 属性指定为 Id 列

我想到的最后一个选项是使用 Employee 类中映射的属性 到带有公式的 AccountManager 表,您可以在其中指定自定义选择以获取所需的值我假设属性 MaxAllowedDiscount,但这也有一些限制,当您使用公式映射属性时,无法插入或更新此属性。

希望这会有所帮助 如果有问题,请告诉我。

【讨论】:

  • 我在数据库模式中添加了一个额外的冗余字段,因此我可以按照我应该的方式映射它。字段本身由数据库中的触发器管理。
【解决方案2】:
public class Employee
{
    public virtual short Number
    {
       get { return (AccountManager == null) ? 0 : AccountManager.Number; }
       set
       {
           if (AccountManager == null)
               AccountManager = new AccountManager();
           AccountManager.Number = value;
       }
    }
    public virtual AccountManager AccountManager { get; set; }
}

或使用 GeneratedBy.Assinged()

public class Employee
{
    public Employee()
    {
        AccountManager = new AccountManager();
    }

    public virtual AccountManager AccountManager
    {
        get;
        set { value.Parent = this; _accountManager = value; }
    }

    public class AccountManager
    {
        Internal protected virtual Employee Parent { get; set; } 

        protected virtual short Number { get { return Parent.Number; } set { } } /*needed because of ID only?*/
        public virtual decimal MaxAllowedDiscount { get; set }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 2014-02-10
    • 2019-04-26
    • 2013-06-08
    • 2012-11-23
    相关资源
    最近更新 更多