与没有ID的表的复杂映射

时间:2011-12-08 16:22:05

标签: c# nhibernate fluent-nhibernate

简短版本:
在NHibernate中是否可以为数据库中没有相应表的类创建映射,并为数据应该来自的每个属性指定?


长版:

我有以下课程:

public class TaxAuditorSettings
{
    private readonly IList<Month> _allowedMonths = new List<Month>();
    private readonly IList<Company> _allowedVgs = new List<Company>();

    public IList<Month> AllowedMonths
    {
        get { return _allowedMonths; }
    }

    public IList<Company> AllowedVgs
    {
        get { return _allowedVgs; }
    }
}

Company是映射到表的普通实体 类Month是一个没有ID或现有映射的简单类(为简洁起见,删除了构造函数和错误检查):

public class Month
{
    public int MonthNumber { get; set; }
    public int Year { get; set; }
}

我的数据库有以下两个表:

TAX_AUDITOR_ALLOWED_COMPANIES只有一列COMPANY_ID,它是表COMPANY的FK,并且具有UNIQUE索引。

TAX_AUDITOR_ALLOWED_MONTHS有两列MONTH_NUMBERYEAR。两个列都有一个UNIQUE索引。

我想映射TaxAuditorSettings,以便我可以向我的NHibernate会话询问此类型的对象,然后NHibernate应将TAX_AUDITOR_ALLOWED_MONTHS的内容放入列表TaxAuditorSettings.AllowedMonthsTAX_AUDITOR_ALLOWED_COMPANIES中引用的公司列入TaxAuditorSettings.AllowedCompanies列表。

这有可能吗?如果是这样,怎么样?如果没有,你会怎么做呢?

请注意:如果需要,我可以更改数据库。

2 个答案:

答案 0 :(得分:2)

不是你要求的但是这里

public TaxAuditorSettings GetAuditorSettings(ISession session)
{
    // assuming there is a ctor taking the enumerables as parameter
    return new TaxAuditorSettings(
        session.CreateSQLQuery("SELECT MONTH_NUMBER, YEAR FROM TAX_AUDITOR_ALLOWED_MONTHS")
            .SetResultTransformer(new MonthResultTransformer())
            .Future<Month>(),
        session.CreateCriteria<Company>()
            .Add(NHibernate.Criterion.Expression.Sql("Id IN (SELECT COMPANY_ID FROM TAX_AUDITOR_ALLOWED_COMPANIES)"))
            .Future<Company>())
}

class MonthResultTransformer : IResultTransformer
{
    public IList TransformList(IList collection)
    {
        return collection;
    }

    public object TransformTuple(object[] tuple, string[] aliases)
    {
        return new Month
        {
            MonthNumber = (int)tuple[0],
            Year = (int)tuple[1],
        }
    }
}

更新:保存

public void SaveOrUpdate(ISession session, TaxAuditorSettings settings)
{
    using (var tx = session.BeginTransaction())
    {
        // get whats in the database first because we dont have change tracking
        var enabledIds = session
            .CreateSqlQuery("SELECT * FROM TAX_AUDITOR_ALLOWED_COMPANIES")
            .Future<int>();

        var savedMonths = session
            .CreateSQLQuery("SELECT MONTH_NUMBER, YEAR FROM TAX_AUDITOR_ALLOWED_MONTHS")
            .SetResultTransformer(new MonthResultTransformer())
            .Future<Month>();

        foreach (var id in settings.AllowedVgs.Except(enabledIds))
        {
            session.CreateSqlQuery("INSERT INTO TAX_AUDITOR_ALLOWED_COMPANIES Values (:Id)")
                .SetParameter("id", id).ExecuteUpdate();
        }

        foreach (var month in settings.AllowedMonths.Except(savedMonths))
        {
            session.CreateSqlQuery("INSERT INTO TAX_AUDITOR_ALLOWED_MONTHS Values (:number, :year)")
                .SetParameter("number", month.Number)
                .SetParameter("year", month.Year)
                .ExecuteUpdate();
        }

        tx.Commit();
    }
}

注意:如果您可以更改数据库,那么清理表格会更容易和更高效

答案 1 :(得分:2)

我会这样做。

public class MonthMap : ClassMap<Month>{
  public MonthMap(){
    CompositeId()
      .KeyProperty(x=>x.MonthNumber,"MONTH_NUMBER")
      .KeyProperty(x=>x.Year);
    Table("TAX_AUDITOR_ALLOWED_MONTHS");
  }
}

在名为COMPANY的{​​{1}}表中添加一列,并将其映射到bool属性。将列更新为1,其中在TaxAuditable中找到匹配的行。然后删除表TAX_AUDITOR_ALLOWED_COMPANIES,因为它没有任何实际用途。

现在您有一个公司,其中包含相应的属性,您可以查询公司TAX_AUDITOR_ALLOWED_COMPANIES TaxAuditable的位置,并将其与true一起传递给方法进行工作/计算等等......也许是这样的事情?

Months