NHibernate的:如何标识ID更新,节省了短暂的实例时?标识、实例、节省、短暂

2023-09-03 04:19:07 作者:温酒对奕

如果我用的session-per-交易,电话:

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

..和实体身份-ID = 0一过性的实例。应上述行自动更新的实体的ID,并进行实例持久​​?还是应该做的等等器transaction.commit?还是我必须以某种方式code,明确?

显然,数据库行的ID(新的,因为瞬态)是自动生成的,并保存为一些数字,但我说的是实际参数实例这里。这是业务逻辑实例。

修改 - 后续的相关问题。

映射:

 公共类StoreMap:ClassMap<店>
{
    公共StoreMap()
    {
        ID(X => x.Id).GeneratedBy.Identity();
        地图(X => x.Name);
        的hasMany(X => x.Staff)// 1:M
            .Cascade.All();
        HasManyToMany(X => x.Products)// M:M关系
            .Cascade.All()
            。表(StoreProduct);
    }
}

公共类EmployeeMap:ClassMap<员工>
{
    公共EmployeeMap()
    {
        ID(X => x.Id).GeneratedBy.Identity();
        地图(X => x.FirstName);
        地图(X => x.LastName);
        参考文献(X => x.Store); // M:1
    }
}

公共类ProductMap:ClassMap<产品>
{
    公共ProductMap()
    {
        ID(X => x.Id).GeneratedBy.Identity();
        地图(X => x.Name).Length(20);
        地图(X => x.Price)。.CustomSqlType(十进制)precision(9).Scale(2);
        HasManyToMany(X => x.StoresStockedIn)
        .Cascade.All()
        。逆()
        。表(StoreProduct);
     }
}
 

EDIT2

类定义:

 公共类商店
{
    公众诠释编号{获得;私定; }
    公共字符串名称{;组; }
    公众的IList<产品>产品{获得;组; }
    公众的IList<员工>工作人员{获得;组; }

    公用存储()
    {
        产品=新的名单,其中,产品>();
        工作人员=新的名单,其中,员工>();
    }


    // AddProduct和放大器; AddEmployee是必需的。 NH需要你之前设置两面
    //它会保存正确

    公共无效AddProduct(产品产品)
    {
        product.StoresStockedIn.Add(本);
        Products.Add(产品);
    }

    公共无效AddEmployee(员工的雇员)
    {
        employee.Store =这一点;
        Staff.Add(员工);
    }
}

公共类员工
{
    公众诠释编号{获得;私定; }
    公共字符串名字{获得;组; }
    公共字符串名字{获得;组; }
    公共店中店{获得;组; }
}

公共类产品
{
    公众诠释编号{获得;私定; }
    公共字符串名称{;组; }
    公共十进制价格{获得;组; }
    公众的IList<店> StoresStockedIn {获得;私定; }
}
 
车管所通知 驾驶证不再是12分,车辆不再 年检 ,有车的赶快了解

解决方案

至于你的问题而言,只要你刷新你的会话是当你的实体持久化到数据库。当保存您的(新)的实体,NHibernate的使用您提供的生成器生成的ID给你。

请记住,身份产生不建议(见这个帖子由Ayende )。 当您使用标识生成器,新的实体保存到数据库时保存,即使你没有刷新到数据库中。出现这种情况的原因是因为NHibernate的需要为您提供的实体,它不能没有做一个往返到数据库中的ID。

有一个更好的解决方案是使用像一个GUID生成器,或者高住低练,如果你想正常值。这样,你可以保存你的实体,而不必实际做一个数据库往返,它可以让你做了很多性能方面(配料想到)。

If I use session-per-transaction and call:

session.SaveOrUpdate(entity) corrected: session.SaveOrUpdateCopy(entity)

..and entity is a transient instance with identity-Id=0. Shall the above line automatically update the Id of the entity, and make the instance persistent? Or should it do so on transaction.Commit? Or do I have to somehow code that explicitly?

Obviously the Id of the database row (new, since transient) is autogenerated and saved as some number, but I'm talking about the actual parameter instance here. Which is the business logic instance.

EDIT - Follow-up, of related problem.

Mappings:

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

Class definitions:

   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; }
}

解决方案

As far as your question is concerned, whenever you flush your session is when your entity is persisted to the database. When saving your (new) entity, NHibernate generates the ID for you using the generator you provided.

Keep in mind that an Identity generator is not recommended (see this post by Ayende). When you use an Identity generator, your new entity is persisted to the database when you save, even if you don't flush to the database. The reason this happens is because NHibernate needs to provide you with an ID for the entity, which it can't do without doing a roundtrip to the database.

A better solution would be to use something like a Guid generator, or HiLo if you want 'normal' values. This way you can save your entity without actually having to do a database roundtrip, which allows you to do a lot more performance wise (batching comes to mind).