我有这个数据库模型:
Candidato 1< - > N Telefone N< - > 1 TipoTelefone
我的表有哪些列
我的课程属性是:
Candidato
=========
public virtual int Id { get; set; }
public virtual string NomeCompleto { get; set; }
public virtual DateTime DataNascimento { get; set; }
public virtual IList<Telefone> Telefones { get; set; }
Telefone
========
public virtual int Id { get; set; }
public virtual Candidato Candidato { get; set; }
public virtual TipoTelefone TipoTelefone { get; set; }
public virtual string Numero { get; set; }
TipoTelefone
============
public virtual int Id { get; set; }
public virtual string Descricao { get; set; }
public IList<Telefone> Telefones { get; set; }
我正在尝试保存Candidato及其Telefones,因为我有许多Telefones的Candidato。
但是当我尝试同时保存我的Candidato及其Telefones时,我遇到了错误。下面我每次尝试某种尝试时都会遇到一些错误:
对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例,或者将属性的级联操作设置为使其自动保存的操作。键入:Entity.Telefone,Entity:Entity.Telefone
object是未保存的瞬态实例 - 在合并之前保存瞬态实例:Entity.Telefone
该类没有标识符属性:Entity.Telefone
当IDENTITY_INSERT设置为OFF时,无法在表'Telefone'中为identity列插入显式值。
Nãoé能转换器um objeto do tipo'NHibernate.Collection.Generic.PersistentGenericSet 1[Entity.Telefone]' no tipo 'System.Collections.Generic.IList
1 [Entity.Telefone]'。
对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例,或者将属性的级联操作设置为使其自动保存的操作。键入:Entity.Telefone,Entity:Entity.Telefone
无法插入:[Entity.Telefone] [SQL:INSERT INTO Telefone(Numero,IdTipoTelefone,Id)VALUES(?,?,?);选择SCOPE_IDENTITY()]
我的项目正在使用NHibernate.Mapping.ByCode,但我怀疑我没有得到正确的地图解决方案。所以,我想知道,如何为这三个实体做出正确的映射。
重要的是要看到我的N:N Telefone表有一个属性Numero,所以这个实体/表不是一个简单的N:N实体,而是一个真实的实体,因为它里面有一个自己的属性。
答案 0 :(得分:0)
这是我的一个老例子。
这是我的“中间”表。
这是一张流利地图
public class EmployeeToJobTitleMatchLinkMap : ClassMap<EmployeeToJobTitleMatchLinkNHEntity>
{
public EmployeeToJobTitleMatchLinkMap()
{
Schema("dbo");
Table("EmployeeToJobTitleMatchLink");
Id(x => x.LinkSurrogateUUID).GeneratedBy.GuidComb();
Map(x => x.PriorityRank);
Map(x => x.JobStartedOnDate);
References(x => x.TheEmployee).Column("TheEmployeeUUID").Not.Nullable().Index("IX_ETJTMLM_TheEmployeeUUID_And_TheJobTitleUUID"); ;/*Bad naming convention with "The", but left here so it can be seen easily in the DDL*/
References(x => x.TheJobTitle).Column("TheJobTitleUUID").Not.Nullable().Index("IX_ETJTMLM_TheEmployeeUUID_And_TheJobTitleUUID"); ;/*Bad naming convention with "The", but left here so it can be seen easily in the DDL*/
}
}
这是(我认为与上面相同)作为hbm.xml文件。
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" schema="dbo" name="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Data.NHibernateSetup.Domain.EmployeeToJobTitleMatchLinkNHEntity, MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Data.NHibernateSetup, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="EmployeeToJobTitleMatchLink">
<id name="LinkSurrogateUUID" type="System.Nullable`1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="LinkSurrogateUUID" />
<generator class="guid.comb" />
</id>
<property name="PriorityRank" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="PriorityRank" />
</property>
<property name="JobStartedOnDate" type="System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="JobStartedOnDate" />
</property>
<many-to-one class="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Data.NHibernateSetup.Domain.EmployeeNHEntity, MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Data.NHibernateSetup, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="TheEmployee">
<column name="TheEmployeeUUID" index="IX_ETJTMLM_TheEmployeeUUID_And_TheJobTitleUUID" not-null="true" />
</many-to-one>
<many-to-one class="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Data.NHibernateSetup.Domain.JobTitleNHEntity, MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Data.NHibernateSetup, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="TheJobTitle">
<column name="TheJobTitleUUID" index="IX_ETJTMLM_TheEmployeeUUID_And_TheJobTitleUUID" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
PriorityRank和JobStartedOnDate将是我“关系中的额外属性”。
这是我找到的另一个hbm.xml文件。
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Glue"
namespace="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Glue.Domain">
<class name="EmployeeToJobTitleMatchLink" lazy="false" schema="MySchema">
<!-- Naming this "Id" might be a requirement, be careful -->
<!--
ISSUE If the generator class is changed from "assigned" to
guid
guid.comb
uuid.string
It will break the ability to create the relationship
-->
<id name="LinkSurrogateUUID">
<generator class="guid.comb"></generator>
</id>
<!--
<id name="LinkSurrogateKey">
<!- -
<generator class="hilo">
<param name="table">HiloHolder</param>
<param name="column">HiloColumn</param>
</generator>
- ->
<generator class="identity">
</generator>
</id>
-->
<many-to-one name="TheEmployee" column="EmployeeUUID" lazy="false" cascade="none" not-null="true" /> <!-- class="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Glue.Domain.Employee, MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Glue" -->
<many-to-one name="TheJobTitle" column="JobTitleUUID" lazy="false" cascade="none" not-null="true" /> <!-- class="MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Glue.Domain.JobTitle, MyCompany.MyTechnology.Prototypes.CompositeAppPOC.Glue" -->
<!--
<many-to-one name="TheEmployee" column="EmployeeKey" lazy="false" cascade="none" not-null="true" />
<many-to-one name="TheJobTitle" column="JobTitleKey" lazy="false" cascade="none" not-null="true" />
-->
<!-- These are "scalar properties of the ~relationship~"-->
<property name="PriorityRank" not-null="true" update="false" />
<property name="JobStartedOnDate" not-null="true" update="false" />
</class>
</hibernate-mapping>
这是我的“中间”域对象
[Serializable]
public partial class EmployeeToJobTitleMatchLink
{
public EmployeeToJobTitleMatchLink()
{
//this.Id = Guid.NewGuid(); /* this works in conjuction with <generator class="assigned"></generator> */
}
//EF Tweaks
public Guid TheEmployeeUUID { get; set; }
public Guid TheJobTitleUUID { get; set; }
public Guid? LinkSurrogateUUID { get; set; }
/* These are "scalar properties of the ~~relationship~~ */
public int PriorityRank { get; set; }
public DateTime JobStartedOnDate { get; set; }
public Employee TheEmployee { get; set; }
public JobTitle TheJobTitle { get; set; }
}
也许这会有所帮助。
我一度解决了这个问题,但现在已经好几年了。
关键是你有一个域对象,它有额外的标量和每个“边”的单个对象。
Telefone
========
public virtual int Id { get; set; }
public virtual Candidato Candidato { get; set; }
public virtual TipoTelefone TipoTelefone { get; set; }
public virtual string Numero { get; set; }
我相信你的Telefone课程是正确的。所以我认为问题在于您的映射。 Fluent或hbm.xml。也许我的“笔记”可以提供帮助。我不能把这个放在评论中。
我有一些巫术,我必须将“中间”对象添加到“外部”对象。
例如:
{
[Serializable]
public partial class Employee
{
public Employee()
{
CommonConstructor();
}
private void CommonConstructor()
{
this.MyEmployeeToJobTitleMatchLinks = new EmployeeToJobTitleMatchLinkCollection();
}
//EF Tweaks
public Guid ParentDepartmentUUID { get; set; }
public Guid? EmployeeUUID { get; set; }
public byte[] TheVersionProperty { get; set; }
//public int? EmployeeKey { get; set; }
// public IDepartment ParentDepartment { get; set; }
public string SSN { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime HireDate { get; set; }
//
public EmployeeToJobTitleMatchLinkCollection MyEmployeeToJobTitleMatchLinks { get; set; }
public void AddJobTitleLink(EmployeeToJobTitleMatchLink link)
{
link.TheEmployee = this;
if (!this.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
this.MyEmployeeToJobTitleMatchLinks.Add(link);
}
if (!link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Add(link);
}
}
public void RemoveJobTitleLink(EmployeeToJobTitleMatchLink link)
{
link.TheEmployee = this;
if (this.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
this.MyEmployeeToJobTitleMatchLinks.Remove(link);
}
if (link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
link.TheJobTitle.MyJobTitleToEmployeeMatchLinks.Remove(link);
}
}
//public ICollection<IParkingAreaDeprecated> MyParkingAreas { get; set; }
//public ICollection<ParkingArea> MyParkingAreas { get; set; }
public IParkingAreaCollection MyParkingAreas { get; set; }
//public void AddParkingArea(IParkingAreaDeprecated pa)
public void AddParkingArea(ParkingArea pa)
{
//pa.MyEmployees.Add(this);
if (!pa.MyEmployees.Contains(this))
{
//pa.AddEmployee(this);//Causes overflow situation
pa.MyEmployees.Add(this);
}
if (!this.MyParkingAreas.Contains(pa))
{
this.MyParkingAreas.Add(pa);
}
}
//public void RemoveParkingArea(IParkingAreaDeprecated pa)
public void RemoveParkingArea(ParkingArea pa)
{
if (pa.MyEmployees.Contains(this))
{
pa.MyEmployees.Remove(this);
}
if (this.MyParkingAreas.Contains(pa))
{
this.MyParkingAreas.Remove(pa);
}
}
public override string ToString()
{
return string.Format("{0}:{1},{2}", this.SSN , this.LastName , this.FirstName );
}
}
}
和另一个“外部”对象
[Serializable]
public partial class JobTitle : IJobTitle
{
public JobTitle()
{
CommonConstructor();
}
private void CommonConstructor()
{
//this.MyEmployees = new List<Employee>();
//this.MyJobTitleToEmployeeMatchLinks = new List<EmployeeToJobTitleMatchLink>();
this.MyJobTitleToEmployeeMatchLinks = new EmployeeToJobTitleMatchLinkCollection();
}
public Guid? JobTitleUUID { get; set; }
//public int? JobTitleKey { get; set; }
//public byte[] TheVersionProperty { get; set; }
public string JobTitleName { get; set; }
public DateTime CreateDate { get; set; }
//public ICollection<Employee> MyEmployees { get; set; }
//public ICollection<IEmployeeToJobTitleMatchLink> MyJobTitleToEmployeeMatchLinks { get; set; }
//public ICollection<EmployeeToJobTitleMatchLink> MyJobTitleToEmployeeMatchLinks { get; set; }
public IEmployeeToJobTitleMatchLinkCollection MyJobTitleToEmployeeMatchLinks { get; set; }
public void AddEmployeeLink(EmployeeToJobTitleMatchLink link)
{
link.TheJobTitle = this;
if (!this.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
this.MyJobTitleToEmployeeMatchLinks.Add(link);
}
if (!link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Add(link);
}
}
public void RemoveEmployeeLink(EmployeeToJobTitleMatchLink link)
{
link.TheJobTitle = this;
if (this.MyJobTitleToEmployeeMatchLinks.Contains(link))
{
this.MyJobTitleToEmployeeMatchLinks.Remove(link);
}
if (link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Contains(link))
{
link.TheEmployee.MyEmployeeToJobTitleMatchLinks.Remove(link);
}
}
}
}
这是我编写所有内容的代码。
注意,我有一个我以前没有讨论的部门实体。 重要的部分是Employee,JobTitle和“link”对象
EmployeeController empRepo = null;
JobTitleController jtRepo = null;
Department idept = new Department() { DepartmentName = "Department One", CreateDate = DateTime.Now };
DepartmentController deptRepo = new DepartmentController();
deptRepo.Add(idept);
Employee emp = new Employee() { ParentDepartment = idept, SSN = "111111111", CreateDate = DateTime.Now, HireDate = DateTime.Now, LastName = "Smith", FirstName = "John" };
JobTitle jtDev = new JobTitle() { JobTitleName = "Developer", CreateDate = DateTime.Now };
JobTitle jtProjectManager = new JobTitle() { JobTitleName = "Project Manager", CreateDate = DateTime.Now };
JobTitle jtDba = new JobTitle() { JobTitleName = "DBA", CreateDate = DateTime.Now };
jtRepo = new JobTitleController();
jtRepo.Add(jtDev);
jtRepo.Add(jtProjectManager);
empRepo = new EmployeeController();
empRepo.AddEmployee(emp);
EmployeeToJobTitleMatchLink link1ToAddThruJobTitleObject = new EmployeeToJobTitleMatchLink();
link1ToAddThruJobTitleObject.TheEmployee = emp;
link1ToAddThruJobTitleObject.TheJobTitle = jtDba;
link1ToAddThruJobTitleObject.JobStartedOnDate = DateTime.Now.AddDays(-1);
link1ToAddThruJobTitleObject.PriorityRank = 5;
jtDba.AddEmployeeLink(link1ToAddThruJobTitleObject);
jtRepo.Add(jtDba);
EmployeeToJobTitleMatchLink link1ToAddThruEmployeeObject = new EmployeeToJobTitleMatchLink();
link1ToAddThruEmployeeObject.TheEmployee = emp;
link1ToAddThruEmployeeObject.TheJobTitle = jtDev;
link1ToAddThruEmployeeObject.JobStartedOnDate = DateTime.Now.AddHours(-1);
link1ToAddThruEmployeeObject.PriorityRank = 1;
EmployeeToJobTitleMatchLink link2ToAddThruEmployeeObject = new EmployeeToJobTitleMatchLink();
link2ToAddThruEmployeeObject.TheEmployee = emp;
link2ToAddThruEmployeeObject.TheJobTitle = jtProjectManager;
link2ToAddThruEmployeeObject.JobStartedOnDate = DateTime.Now.AddYears(5);
link2ToAddThruEmployeeObject.PriorityRank = 2;
emp.AddJobTitleLink(link1ToAddThruEmployeeObject);
emp.AddJobTitleLink(link2ToAddThruEmployeeObject);
empRepo.Upsert(emp);