NHibernate:保存瞬态实例时,身份ID如何更新?

时间:2011-02-04 08:39:08

标签: c# .net database nhibernate fluent-nhibernate

如果我使用session-per-transaction并致电:

session.SaveOrUpdate(实体) 已更正:
session.SaveOrUpdateCopy(实体)

..和entity是一个身份-Id = 0的瞬态实例。以上行是否会自动更新实体的Id,并使实例持久化?或者它应该在transaction.Commit上这样做吗?或者我必须以某种方式明确地编码?

显然数据库行的Id(新的,因为瞬态)是自动生成的并保存为某个数字,但我在这里谈论的是实际的参数实例。哪个是业务逻辑实例。


编辑 - 相关问题的跟进。

映射:

public class StoreMap : ClassMap<Store>
{
    public StoreMap()
    {
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x =>  x.Name);
        HasMany(x => x.Staff)    // 1:m
            .Cascade.All();       
        HasManyToMany(x => x.Products)  // m:m
            .Cascade.All()
            .Table("StoreProduct");    
    }
}

public class EmployeeMap : ClassMap<Employee> 
{
    public EmployeeMap()
    {
        Id(x => x.Id).GeneratedBy.Identity();   
        Map(x => x.FirstName);
        Map(x => x.LastName);
        References(x => x.Store);    // m:1
    }
}

public class ProductMap : ClassMap<Product>
{
    public ProductMap() 
    {
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Name).Length(20);
        Map(x => x.Price).CustomSqlType("decimal").Precision(9).Scale(2);
        HasManyToMany(x => x.StoresStockedIn)
        .Cascade.All()
        .Inverse()
        .Table("StoreProduct");
     } 
}

EDIT2

课程定义:

   public class Store
{
    public int Id { get; private set; }
    public string Name { get; set; }
    public IList<Product> Products { get; set; }
    public IList<Employee> Staff { get; set; }

    public Store()
    {
        Products = new List<Product>();
        Staff = new List<Employee>();
    }


    // AddProduct & AddEmployee is required. "NH needs you to set both sides before
    // it will save correctly" 

    public void AddProduct(Product product)
    {
        product.StoresStockedIn.Add(this);
        Products.Add(product);
    }

    public void AddEmployee(Employee employee)
    {
        employee.Store = this;
        Staff.Add(employee);
    }
}

public class Employee
{
    public int Id { get;  private set; }
    public string FirstName { get;  set; }
    public string LastName { get;  set; }
    public Store Store { get; set; }
}

public class Product
{
    public int Id { get; private set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public IList<Store> StoresStockedIn { get; private set; }
}

4 个答案:

答案 0 :(得分:3)

就您的问题而言,每当您刷新会话时,您的实体都会持久保存到数据库。保存(新)实体时,NHibernate会使用您提供的生成器为您生成ID。

请注意,不建议使用Identity生成器(请参阅this post by Ayende)。 使用Identity生成器时,即使未刷新到数据库,新实体也会在保存时保留到数据库中。发生这种情况的原因是因为NHibernate需要为实体提供一个ID,如果没有对数据库进行往返,它就无法做到。

更好的解决方案是使用像Guid生成器或HiLo这样的东西,如果你想要'普通'值。通过这种方式,您可以保存实体,而无需实际进行数据库往返,这样可以更好地执行数据(请记住批处理)。

答案 1 :(得分:2)

我不确定我理解你的问题。当刷新会话时(例如,通过提交事务),实际保存到数据库。调用SaveOrUpdate()本身并不保存实体,它只是通知会话在刷新会话时该实体将被保存。

假设实体的ID映射到数据库中的标识字段,并且您的映射告诉NHibernate该标识是由数据库设置的,那么数据库设置的ID将在保存时设置为实体的ID

答案 2 :(得分:1)

Nhibernate将在SaveOrUpdate调用之后设置实体的ID属性。

答案 3 :(得分:0)

我注意到我通过打电话来保存:

session.SaveOrUpdateCopy(entity); 

..不更新Id。但是改为:

session.SaveOrUpdate(entity);

..瞬态实体的ID 更新。

我可能误解了documentation (?).. Section 9.4.2说:

SaveOrUpdateCopy(Object o)...如果给定的实例未保存或数据库中不存在,NHibernate将保存它并将其作为新的持久化实例返回。

仅仅是我,还是听起来不像是一个瞬态对象(未保存),将“作为持久性”返回?这是不是意味着更新的ID?希望澄清如何正确解释这句话(?)