C# 对象与使用NHibernate和fluent保存子记录的目标类型不匹配
我有两个班 联系方式C# 对象与使用NHibernate和fluent保存子记录的目标类型不匹配,c#,nhibernate,one-to-many,fluent,C#,Nhibernate,One To Many,Fluent,我有两个班 联系方式 public class Contact : IDisposable { private String email; private String name; private String address; private Guid recordId; public virtual String Id { get; set; } public virtual String Forename { get; set; }
public class Contact : IDisposable
{
private String email;
private String name;
private String address;
private Guid recordId;
public virtual String Id { get; set; }
public virtual String Forename { get; set; }
public virtual String Surname { get; set; }
public virtual String PictureUrl { get; set; }
public virtual String HomeNumber { get; set; }
public virtual String MobileNumber { get; set; }
public virtual DateTime LastUpdated { get; set; }
public virtual Byte[] Picture { get; set; }
[XmlIgnore]
public virtual IList<PostalAddress> PostalAddresses { get; set; }
public virtual String Address
{
get
{
return address;
}
set
{
address = value;
if (PostalAddresses == null) PostalAddresses = new List<PostalAddress>();
if (!String.IsNullOrEmpty(address))
{
PostalAddress postalAddress = new PostalAddress(Address) { OwnedBy = RecordId };
PostalAddresses.Add(postalAddress);
}
}
}
public virtual String Email {
get
{
return email; ;
}
set
{
if (String.IsNullOrEmpty(name))
ExtractName(value);
email = value;
}
}
public virtual String Name
{
get
{
return name;
}
set
{
// if name is actually an email address extract the name part and use that.
if (value.Contains('@'))
ExtractName(value);
else
{
// if name is just some text then use the first word as forename and the rest
// for a surname
name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(value);
if (name.Contains(' ') && String.IsNullOrEmpty(Forename) && String.IsNullOrEmpty(Surname))
{
String[] splitName = name.Split(' ');
Forename = splitName[0].Trim();
Surname = name.Substring(Forename.Length).Trim(); ;
}
else
{
if (String.IsNullOrEmpty(Forename)) Forename = name;
}
}
}
}
private void ExtractName ( String email )
{
}
/// <summary>
/// Extract numbers from what would be the name
/// </summary>
/// <param name="oldString"></param>
/// <returns></returns>
private String ExtractNumber ( String oldString )
{
}
/// <summary>
/// Extract the forename and surname from an email - replacing .-_ with spaces
/// </summary>
/// <param name="newEmail"></param>
/// <param name="SplitChar"></param>
private void ExtractNameFromEmail(String newEmail,Char SplitChar)
{
}
public virtual Guid Owner { get; set; }
public virtual Guid RecordId
{
get
{
return recordId;
}
set
{
recordId = value;
}
}
public Contact()
{
RecordId = Guid.NewGuid();
Name = String.Empty;
Email = String.Empty;
Forename = String.Empty;
Surname = String.Empty;
Address = String.Empty;
PictureUrl = String.Empty;
PostalAddresses = new List<PostalAddress>();
}
public void Dispose()
{
Name = String.Empty;
Email = String.Empty;
Forename = String.Empty;
Surname = String.Empty;
Address = String.Empty;
PictureUrl = String.Empty;
PostalAddresses = null;
}
}
但是,当我尝试用以下行保存地址时
Session.Save(Contact.PostalAddresses[0])代码>
它失败了,出现以下异常
获取Cloud.BusinessObjects.Contacts.Contact.RecordId时发生异常
和一个内在的例外
对象与目标类型不匹配
我确信问题出在我映射联系人和地址之间关系的方式上——但我一辈子都看不出我做错了什么。提前有什么建议和感谢吗?重点是,使用的映射有很多和引用是用于对象关系映射。PostLaddress正在引用联系人(而不是其RecordId-GUID)。联系人有很多地址
必须表示为
public class PostalAddress : IDisposable
{
...
public virtual Contact OwnedBy { get; set; } // the reference
这应该是可行的,因为NHibernate将能够处理关系的两端(PostLaddress和Contact),就像处理对象一样
注意:这里我们还可以看到Fluent映射的优点。它确实用“英语”描述了映射是如何工作的。谁引用什么,谁有很多关系
请尝试在这里阅读更多
public class ContactMap : ClassMap<Contact>
{
public ContactMap()
{
Table("Contacts");
Id(x => x.RecordId);
HasMany<PostalAddress>(x => x.PostalAddresses)
.KeyColumns.Add("RecordId", mapping => mapping.Name("RecordId"));
Map(x => x.Id);
Map(x => x.Email);
Map(x => x.Forename);
Map(x => x.HomeNumber);
Map(x => x.LastUpdated);
Map(x => x.MobileNumber);
Map(x => x.Owner);
Map(x => x.Picture);
Map(x => x.PictureUrl);
Map(x => x.Surname);
}
}
public class AddressMap : ClassMap<PostalAddress>
{
public AddressMap()
{
Table("PostalAddresses");
Id(x => x.RecordId).GeneratedBy.Assigned();
Map(x => x.AddressType);
Map(x => x.Address).Column("AddressText");
Map(x => x.Locality);
Map(x => x.Town);
Map(x => x.County);
Map(x => x.Country);
Map(x => x.Postcode);
References(x => x.OwnedBy)
.Class<Contact>().Columns("OwnedBy");
}
}
public void Insert ( Contact Contact)
{
ISessionFactory factory = null;
ITransaction transaction = null;
try
{
if (Contact.RecordId == null) Contact.RecordId = Guid.NewGuid();
factory = CreateSessionFactory();
using (var session = factory.OpenSession())
{
transaction = session.BeginTransaction();
if (Contact.PostalAddresses.Count > 0)
session.Save(Contact.PostalAddresses[0]);
session.Save(Contact);
transaction.Commit();
}
}
catch (System.Exception ex)
{
throw ex;
}
}
public class PostalAddress : IDisposable
{
...
public virtual Guid OwnedBy { get; set; } // this is not a Reference
public class PostalAddress : IDisposable
{
...
public virtual Contact OwnedBy { get; set; } // the reference