NHibernate - 一对多只是不使用SQLite

Alt*_*yyr 1 sqlite nhibernate

TL; DR;
NHibernate反向关系正在发挥作用Azure-SQL,MSSQL2012但不是SQLite

描述:
我目前正在对我的Asp.Net MVC应用程序进行单元测试,并FluentMigrator在SQLite上设置我的Unittest .

创建数据库后,我设置了一些我需要的基本条目.
其中一个是产品.
A Product有很多ProductSuppliers,ProductSupplier有很多ProductSupplierPrices

public class Product
{
    public virtual long Id { get; set; }

    public virtual string Number { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }
    //more properties
    public virtual IList<ProductSupplier> Suppliers { get; set; }
    //more properties
}

public class ProductSupplier 
{
    public virtual long Id { get; set; }

    public virtual Product Product { get; set; }
    public virtual Supplier Supplier { get; set; }

    public virtual IList<ProductSupplierPrice> Prices { get; set; }
}

public class ProductSupplierPrice : IHaveId
{
    public virtual long Id { get; set; }
    public virtual ProductSupplier ProductSupplier { get; set; }
    public virtual decimal FromAmount { get; set; }
    public virtual decimal Price { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

建立:

  1. 创建供应商
  2. 创建产品
  3. 创建ProductSupplier
  4. 创建ProductSupplierPrice

测试:

Product product = this.session.Load<Product>((long)1);
ProductSupplier productSupplier = product.Suppliers.First(); //<-- Suppliers are null; therefore throws an exception
Run Code Online (Sandbox Code Playgroud)

如果我单独加载它们来检查关系:

productSupplierPrice.ProductSupplier <--- Correct Supplier

productSupplier.Prices <-- Null 
productSupplier.Product <-- Product with Id 1

product.Suppliers <-- Null
Run Code Online (Sandbox Code Playgroud)

所以对我而言,多对一方向似乎是正确的,但是一对多(反向关系)不起作用.

问题仅存在于我的Unittest(SQLite)中,App本身运行Azure-SQL并且运行正常.

编辑:
与FluentnHibernate的映射

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        Id(x => x.Id);
        HasMany(x => x.Suppliers).Inverse().Cascade.DeleteOrphan().BatchSize(20);
       //many more mappings
    }
}

public ProductSupplierMap()
{
    Id(x => x.Id);
    References(x => x.Product);
    References(x => x.Supplier);
    Map(x => x.IsMainSupplier);
    Map(x => x.SupplierProductNumber);
    Map(x => x.CopperSurcharge);
    HasMany(x => x.Prices).Inverse().Cascade.DeleteOrphan().BatchSize(20);
}

public ProductSupplierPriceMap()
{
    Id(x => x.Id);
    References(x => x.ProductSupplier);
    Map(x => x.FromAmount);
    Map(x => x.Price);
}
Run Code Online (Sandbox Code Playgroud)

Edit2 - 创建数据库条目:

Product product = new Product()
{
    Type = ProductType.Purchase,
    Dispatcher = session.Load<Employee>(employeeId),
    Number = "100.10-1000",
    Name = "Testproduct",
    //Lots of Properties
    Suppliers =  new List<ProductSupplier>()
};
session.SaveOrUpdate(product);

ProductSupplier productSupplier = new ProductSupplier()
{
    Product = product,
    Supplier = session.Load<Supplier>((long)1),
    IsMainSupplier = true,
    SupplierProductNumber = "Artikel123456",
    CopperSurcharge = CopperSurchargeType.DEL700,
    Prices = new List<ProductSupplierPrice>()
};
session.Save(productSupplier);

ProductSupplierPrice productSupplierPrice = new ProductSupplierPrice()
{
    ProductSupplier = productSupplier,
    FromAmount = 1,
    Price = 5
};
session.Save(productSupplierPrice);
Run Code Online (Sandbox Code Playgroud)

编辑3.1:

public static ISession InitializeDatabase()
{
    NHibernateSessionHolder.CreateSessionFactory();
    session = NHibernateSessionHolder.OpenSession();
    CreateBaseEntries(); //Creates Employees, Supplier, Customer etc
    return session;
}
Run Code Online (Sandbox Code Playgroud)

Naj*_*era 5

根据Ayende的文章,您需要清除插入/更新和查询之间的会话:

session.Clear();
Run Code Online (Sandbox Code Playgroud)

似乎是一个会话管理,我不确定为什么会话应该是干净的,但是会话提供了你的原始实例(与你提供的保存,存储在会话缓存中相同)而不是延迟加载的代理.

private long CreatePurchaseOrder()
{
    session.Clear();

    var product = this.session.Load<Product>((long)1);
    var productSupplier = product.Suppliers.First();
    var productSupplierPrice = productSupplier.Prices.First();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)