FluentHibernate: отображение составных первичных ключей расширено до многих уровней - PullRequest
0 голосов
/ 10 ноября 2011

У меня есть три таблицы: BillHead, BillDet, BilDetDet со следующей диаграммой БД
DB Diagram

PK и FK определены ниже:

Table Name     Primary Key                    Foreign Key          FK Table
--------------------------------------------------------------------------------
BillHead         BillNo                            -                  -
BillDet         BillNo, SerialNo                BillNo              BillHead  
BilDetDet    BillNo, SerialNo, DetialSeqNo   BillNo, SerialNo       BillDet   

Я сделал отображение, и псевдокод приведен ниже:

//BillHeadMap

public class BillHeadMap : ClassMap<BillHead>
{
    public BillHeadMap()
    {
        Table("BillHead");
        LazyLoad();
        Id(x => x.BillNo).GeneratedBy.Identity().Column("BillNo");
        Map(x => x.CustName).Column("CustName").Not.Nullable().Length(50);
        Map(x => x.BillAmt).Column("BillAmt").Not.Nullable();
        HasMany(x => x.BillDets).KeyColumn("BillNo").Cascade.All().Inverse();
    }
}

//BillDetMap
public class BillDetMap : ClassMap<BillDet>
{
    public BillDetMap()
    {
        Table("BillDet");
        LazyLoad();
        CompositeId()
            .KeyReference(x => x.BillHead, "BillNo")
            .KeyProperty(x => x.SerialNo, "SerialNo");
        Map(x => x.ItemName).Column("ItemName").Not.Nullable().Length(20);
        Map(x => x.ItemAmt).Column("ItemAmt").Not.Nullable();
        HasMany(x => x.BilDetDets).KeyColumns.Add("BillNo", "SerialNo").Cascade.All().Inverse().Table("BilDetDet");
    }
}

//BilDetDetMap
public class BilDetDetMap : ClassMap<BilDetDet>
{
    public BilDetDetMap()
    {
        Table("BilDetDet");
        LazyLoad();
        CompositeId()
            .KeyProperty(x => x.BillNo, "BillNo")
            .KeyProperty(x => x.SerialNo, "SerialNo")
            .KeyProperty(x => x.DetailSeqNo, "DetailSeqNo");
        Map(x => x.DetailAmt).Column("DetailAmt").Not.Nullable();
    }
}  

Когда я пытался сохранить Билл, используя следующий код:

using (var sqlTrans = session.BeginTransaction()) {
    BillHead bh = new BillHead() { CustName = "Rama", BillAmt = 50000.00M };
    BillDet bd = new BillDet() { SerialNo = 101, ItemName = "BG", ItemAmt = 50000.00M };
    BilDetDet dd1 = new BilDetDet() { DetailSeqNo = 1001, DetailAmt = 20000.00M };
    BilDetDet dd2 = new BilDetDet() { DetailSeqNo = 1002, DetailAmt = 30000.00M };

    AddFirstLevelBillBetails(bd, dd1, dd2);
    AddSecondBillDetailBill(bh, bd);

    session.Save(bh);
    sqlTrans.Commit();
}


private void AddSecondBillDetailBill(BillHead bh, params BillDet[] bds)
{
    foreach (BillDet bd in bds) {
        bh.AddNewBillDetail(bd);
        bd.BillHead = bh;
    }
}

private void AddFirstLevelBillBetails(BillDet bd, params BilDetDet [] bdds)
{
    foreach (BilDetDet bdd in bdds) {
        bd.AddBillDetail(bdd);
        bdd.BillDet = bd;
    }
}

Я получаю следующую ошибку в операторе sqlTrans.Commit ().

не удалось вставить: [Sample.CustomerService.Domain.BilDetDet # Sample.CustomerService.Domain.BilDetDet] [SQL: ВСТАВИТЬ В BilDetDet (DetailAmt, BillNo, SerialNo, DetailSeqNo) ЦЕННОСТИ (?,?,?,?)]

Я профилировал это с помощью SQL Server Profiler и обнаружил, что для таблиц BillHead и BillDet создаются правильные операторы вставки. Когда дело доходит до таблицы BilDetDet, столбцам BillNo и SerialNo не назначаются никакие значения (они только нулевые). Я прикрепил текст профиля:

exec sp_executesql N'INSERT INTO BilDetDet (DetailAmt, BillNo, SerialNo, DetailSeqNo) VALUES (@p0, @p1, @p2, @p3)',N'@p0 decimal(28,5),@p1 int,@p2 int,@p3 
int',@p0=100.21000,@p1=0,@p2=0,@p3=101

Пожалуйста, обратите внимание, что столбцам BillNo и SerialNo назначается ноль и, следовательно, sql завершается ошибкой.

Пожалуйста, исправьте сопоставления. Заранее спасибо.

1 Ответ

2 голосов
/ 10 ноября 2011

не должно быть:

public BilDetDetMap()
{
    CompositeId()
        .KeyReference(x => x.BillDet, "BillNo", "SerialNo")
        .KeyProperty(x => x.DetailSeqNo, "DetailSeqNo");
}

Обновление: мой источник информации

  • Intellisense
  • отображение составных ключей
  • скопируйте и вставьте свой код в консольное приложение со следующим кодом

    var config = Fluently.Configure()
        .Database(SQLiteConfiguration.Standard.InMemory().ShowSql().FormatSql())
        .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())
        )
        .BuildConfiguration();
    
        var sf = config.BuildSessionFactory();
    
        using (var session = sf.OpenSession())
        {
            new SchemaExport(config).Execute(true, true, false, session.Connection, null);
    
            // copy in test code here
        }
    

: D

...