C# NHibernate:保存临时实例时如何更新标识Id?
如果我使用每个事务的会话并调用: 会话。保存或更新(实体)更正:C# NHibernate:保存临时实例时如何更新标识Id?,c#,.net,database,nhibernate,fluent-nhibernate,C#,.net,Database,Nhibernate,Fluent Nhibernate,如果我使用每个事务的会话并调用: 会话。保存或更新(实体)更正: 会话。保存或更新副本(实体) ..实体是标识Id为0的临时实例。上述行是否应自动更新实体的Id,并使实例持久化?或者它应该在transaction.Commit上这样做?还是我必须以某种方式显式地编写代码 显然,数据库行的Id(新的,因为是暂时的)是自动生成的,并保存为某个数字,但我在这里讨论的是实际的参数实例。这是业务逻辑实例 编辑-跟进相关问题 映射: public class StoreMap : ClassMap<
会话。保存或更新副本(实体) ..实体是标识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");
}
}
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; }
}
公共类存储映射:类映射
{
公共存储地图()
{
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()
.表格(“存储产品”);
}
}
公共类EmployeeMap:ClassMap
{
公共雇员地图()
{
Id(x=>x.Id).GeneratedBy.Identity();
Map(x=>x.FirstName);
Map(x=>x.LastName);
引用(x=>x.Store);//m:1
}
}
公共类ProductMap:ClassMap
{
公共产品地图()
{
Id(x=>x.Id).GeneratedBy.Identity();
Map(x=>x.Name).Length(20);
地图(x=>x.Price).CustomSqlType(“十进制”).Precision(9).Scale(2);
HasManyToMany(x=>x.StoresStockedIn)
.Cascade.All()
.Inverse()
.表格(“存储产品”);
}
}
EDIT2 类定义:
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");
}
}
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; }
}
公共类存储
{
public int Id{get;private set;}
公共字符串名称{get;set;}
公共IList产品{get;set;}
公共IList职员{get;set;}
公共商店()
{
产品=新列表();
职员=新名单();
}
//AddProduct和AddEmployee是必需的。“NH需要您在
//它将正确保存“
公共产品(产品)
{
product.StoresStockedIn.Add(此);
产品。添加(产品);
}
公共无效添加员工(员工)
{
employee.Store=this;
Staff.Add(雇员);
}
}
公营雇员
{
public int Id{get;private set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共存储{get;set;}
}
公共类产品
{
public int Id{get;private set;}
公共字符串名称{get;set;}
公共十进制价格{get;set;}
公共IList存储stockedin{get;private set;}
}
我不太明白你的问题。在刷新会话时(例如,通过提交事务),将实际保存到数据库。调用SaveOrUpdate()本身并不保存实体,它只是通知会话在刷新会话时将保存实体
假设实体的ID映射到数据库中的标识字段,并且映射告诉NHibernate该标识是由数据库设置的,则数据库设置的ID将在保存时设置为实体的ID。NHibernate将在SaveOrUpdate调用之后设置实体的ID属性 我注意到我通过打电话保存了:
session.SaveOrUpdateCopy(entity);
..不更新Id,但通过更改为:
session.SaveOrUpdate(entity);
..将更新瞬态实体的Id
我可能误解了这句话:
SaveOrUpdateCopy(对象o)。。。如果给定实例未保存或不存在于数据库中,NHibernate将保存该实例并将其作为新的持久实例返回。
它只是我,还是听起来不像是一个临时对象(未保存),将“作为持久对象返回”?这不意味着更新了身份证吗?请澄清如何正确解释这句话(?)就您的问题而言,无论何时刷新会话,都是在实体持久化到数据库时。保存(新)实体时,NHibernate使用您提供的生成器为您生成ID 请记住,不建议使用标识生成器(请参阅)。 使用标识生成器时,即使未刷新到数据库,在保存时也会将新实体持久化到数据库。发生这种情况的原因是,NHibernate需要为您提供实体的ID,如果不来回访问数据库,它就无法做到这一点
更好的解决方案是使用Guid生成器,如果需要“正常”值,则使用HiLo。通过这种方式,您可以保存实体,而无需实际执行数据库往返操作,这使您能够在性能方面做更多的工作(我想到了批处理)。是的,您的意思是;在代码行transaction.Commit()之后,实体的Id属性应反映数据库行的设置?我询问的原因是我跟踪代码(在我的repository.SaveOrUpdate方法中),实体的id始终为0,即使在.Commit之后也是如此。所以我想确认应该在什么时候设置。如果提交后您的id为0,则表明您没有正确映射生成器。谢谢!这很好,得到了坚定的证实。那一定和我的另一个问题有关。我想这个身份证问题可能是那个问题的原因。但我认为这是一种结果,而不是原因。顺便提一下“生成器”是指标准的实体类映射吗?或ISessionFactory配置?更改Id(x=>x.Id);到Id(x=>x.Id).GeneratedBy.Identity();我这样做了(认为它是默认自动生成的,但不确定)。但是它仍然没有更新entity-Id。我想这是有道理的,因为会话范围可能很长。但我的Id仍然是0..FluentNHibernate根据OP的标签判断。正常