NHibernate通过代码和SQLite数据库进行映射:保存多对一的父子实体,子类获取null外键

ror*_*.ap 5 .net c# nhibernate many-to-one nhibernate-mapping-by-code

这个问题的变化已被要求,并回答了很多次,答案有很多重叠的细节.我已经尝试过这些答案提出的许多不同的事情,但是没有一个在我的案例中有效.

我有一个带有父表和子表的SQLite数据库.这是一个非常简单的设置.我正在使用NHibernate 4.0.4进行代码映射而不是流畅,因为我建议前者是新的,而后者是改进的.

实体:

public class BillingItem
{
    public virtual int ID { get; set; }
    public virtual string Name { get; set; }
    // ... other properties
    public virtual ICollection<PaymentItem> PaymentItems { get; set; }

    public BillingItem()
    {
        PaymentItems = new List<PaymentItem>();
    }
}

public class PaymentItem
{
    public virtual int ID { get; set; }
    public virtual BillingItem OwningBillingItem { get; set; }
    // ... other properties
}
Run Code Online (Sandbox Code Playgroud)

BillingItem映射:

public class BillingItemMapping : ClassMapping<BillingItem> 
{
    public BillingItemMapping()
    {
        Table("BillingItems");
        Lazy(true);
        Id(x => x.ID, map => map.Generator(Generators.Identity));

        Set(x => x.PaymentItems, c =>
            {
                c.Key(k =>
                    {
                        k.Column("ID");
                        k.ForeignKey("BillingItemID");
                    });
                c.Inverse(true);
                c.Cascade(Cascade.None);
            },
            r => r.OneToMany(o => { }));

        Property(x => x.Name);
        // ... other properties
    }
}
Run Code Online (Sandbox Code Playgroud)

PaymentItem映射:

public class PaymentItemMapping  : ClassMapping<PaymentItem> 
{
    public PaymentItemMapping()
    {
        Table("PaymentItems");
        Lazy(true);
        Id(x => x.ID, map => map.Generator(Generators.Identity));

        ManyToOne(x => x.OwningBillingItem, m =>
            {
                m.Column("ID");
                m.Update(false);
                m.Insert(false);
                m.Cascade(Cascade.None);
                m.Fetch(FetchKind.Join);
                m.NotFound(NotFoundMode.Exception);
                m.Lazy(LazyRelation.Proxy);
                m.ForeignKey("BillingItemID");
            });

        Property(x => x.DueDate, map => map.NotNullable(true));
        // ... other properties.
    }
}
Run Code Online (Sandbox Code Playgroud)

仓库:

public void Add(BillingItem toAdd)
{
    using (ISession session = Helpers.NHibernateHelper.OpenSession())
    using (ITransaction tran = session.BeginTransaction())
    {
        session.Save(toAdd);

        foreach (var pi in toAdd.PaymentItems)
        {
            session.Save(pi);
        }

        tran.Commit();
    }
}
Run Code Online (Sandbox Code Playgroud)

商业逻辑:

var bi = new BillingItem()
{
    Name = Guid.NewGuid().ToString(),
    // ... others..
};

var pi = new PaymentItem()
{
    OwningBillingItem = bi,
    DueDate = DateTime.Now.AddDays(3)
    // ... others..
};

bi.PaymentItems.Add(pi);
var repo = new Repository();
repo.Add(bi);
Run Code Online (Sandbox Code Playgroud)

正如建议这个答案(和这个这个和许多其他人),我已经确定设置Inverse(true)在我的Set(子集)中BillingItemMapping.我还在对象中设置了双向引用PaymentItem:

OwningBillingItem = bi
Run Code Online (Sandbox Code Playgroud)

BillingItem对象:

bi.PaymentItems.Add(pi);
Run Code Online (Sandbox Code Playgroud)

我觉得我已经按照它应该的方式设置了所有其他内容,并且我根据各种其他来源的建议对许多映射设置进行了修改.但是,我只是想不通为什么它不起作用.

问题是,我无法获取记录中的外键列PaymentItem来保存ID BillingItem.如果我将列设置为不允许空值(这应该是它的方式),我得到一个空约束异常.如果我将其设置为允许空值(用于测试),它只是设置为null(显然).

我究竟做错了什么?

zhi*_*min 2

呵呵,你的有问题PaymentItemMapping,正确的映射应该是这样的:

public class PaymentItemMapping : ClassMapping<PaymentItem> {

    public PaymentItemMapping() {
        Table("PaymentItems");
        Lazy(true);
        Id(x => x.ID, map => map.Generator(Generators.Identity));

        ManyToOne(x => x.OwningBillingItem, m => {
            //Do not map to m.Column("ID");
            m.Column("BillingItemID");
            // BillingItemID can be insert and update
            m.Update(true);
            m.Insert(true);
            m.Cascade(Cascade.None);
            m.Fetch(FetchKind.Join);
            m.NotFound(NotFoundMode.Exception);
            m.Lazy(LazyRelation.Proxy);
            m.ForeignKey("BillingItemID");
        });

        Property(x => x.DueDate, map => map.NotNullable(true));
        // ... other properties.
    }
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

638 次

最近记录:

9 年 前