使用错误的(棕色地块)数据库模式映射一对一关系

时间:2010-12-07 11:29:32

标签: nhibernate nhibernate-mapping brownfield

我必须在NHibernate中建立这种关系模型(简化代码以保持主题) - 员工可以是帐户管理员(因此,它是可选的):

表员工(身份证号码,号码,姓名) 表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完成。顺便说一句:我可以更改类,映射等,但我不能更改表结构,因为它的棕色区域状态(旧应用程序有200多万行代码,近1000种形式)。

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

2 个答案:

答案 0 :(得分:0)

你的问题让我想到了类的继承,你可以将你的类AccountManager映射为Employee的子类,然后你就可以做你想做的事情,我会为你测试一个映射,但是当你设计表时方式无法解决您的需求,因为您需要在映射中注意两点:

  1. Employee表中的number属性应该是AccountManager的一种唯一类型的foreing键,以便用作外键,但即便如此,因为NHibernate,当您尝试插入新的Account Manager时在人员表中插入一条记录,然后将人员的ID分配给AccountManager的数字列,以满足您的需要。
  2. 将该关系映射为多对一不会因同一原因而起作用。 AccountManager的Number属性是主键吗?是独特的?如果没有主键,NHibernate无法工作,因此为了使该关系工作,您必须将AccountManager的Number propety指定为Id列
  3. 我想到的最后一个选项是使用Employee类中映射的属性 到AccountManager表的公式,您可以在其中指定自定义选择以获取您需要的值我假设属性MaxAllowedDiscount,但这也有一些限制,当您使用公式映射属性时,此属性不能插入也不更新。 / p>

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

答案 1 :(得分:0)

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; }
}

或使用Generated By.Assigned()

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 }
    }
}