首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NHibernate -一对一-很多人只是不与SQLite合作

NHibernate -一对一-很多人只是不与SQLite合作
EN

Stack Overflow用户
提问于 2015-11-12 08:09:01
回答 2查看 188关注 0票数 1

TL;DR;

NHibernate反向关系适用于Azure-SQLMSSQL2012,而不是SQLite

描述:

我目前正在统一测试我的Asp.Net MVC应用程序,并在SQLite上用FluentMigrator设置我的Unittest。

在创建数据库之后,我设置了一些我需要的基本条目。

其中之一就是产品。

Product有很多ProductSuppliersProductSupplier有很多ProductSupplierPrices

代码语言:javascript
复制
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; }
}

设置:

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

测试:

代码语言:javascript
复制
Product product = this.session.Load<Product>((long)1);
ProductSupplier productSupplier = product.Suppliers.First(); //<-- Suppliers are null; therefore throws an exception

如果我单独加载它们以检查它们之间的关系:

代码语言:javascript
复制
productSupplierPrice.ProductSupplier <--- Correct Supplier

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

product.Suppliers <-- Null

因此,在我看来,多对一的方向是正确的,但一对多(反向关系)却不起作用。

问题只存在于我的Azure-SQL (SQLite)应用程序本身,运行在上,并且运行良好。

编辑:

带有FluentnHibernate的映射

代码语言:javascript
复制
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);
}

Edit2 -创建数据库-条目:

代码语言:javascript
复制
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);

编辑3.1:

代码语言:javascript
复制
public static ISession InitializeDatabase()
{
    NHibernateSessionHolder.CreateSessionFactory();
    session = NHibernateSessionHolder.OpenSession();
    CreateBaseEntries(); //Creates Employees, Supplier, Customer etc
    return session;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-17 08:57:28

根据艾因德的文章,您需要清除insert/update和查询之间的会话:

代码语言:javascript
复制
session.Clear();

似乎是会话管理,我不知道为什么会话应该是干净的,但是会话提供了原始实例(与存储在会话缓存中的保存实例相同),而不是用来延迟加载的代理。

代码语言:javascript
复制
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;
}
票数 5
EN

Stack Overflow用户

发布于 2015-11-17 23:45:56

抱歉迟到了回复

在单元测试中,您使用相同的会话来创建和获取实体。这是不正确的,因为后续的fetch从第一级缓存返回实体,这些实体没有正确地设置它们的图形。

So....either使用不同的会话作为快速修复,我在"DatabaseSetUpHelper“的方法"InitializeDatabase()”中添加了"session.Clear()“。清除会话会清除第一级缓存,并强制NH再次从DB获取数据,生成的实体将正确地设置它们的图形。

代码语言:javascript
复制
    public static ISession InitializeDatabase()
    {
        NHibernateSessionHolder.CreateSessionFactory();
        session = NHibernateSessionHolder.OpenSession();
        CreateBaseEntries();
        session.Clear(); // notice this!!! this clears first level cache of session, thus forcing fetching of data from DB
        return session;
    }

注意:我的快速修复不是最终的解决方案,它只是显示会话的行为。在适当的解决方案中,您必须使用不同的会话。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33666824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档