FluentNhibernate 级联 - 未保存父 ID
FluentNhibernate Cascading - Not Saved Parent Id
我的 nhibernate 有问题。
我的代码,
基础实体:
public abstract class BaseEntity : IEntity<BaseEntity, int>, IDisposable
{
public virtual int Id { get; set; }
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
IAuditInfo:
public interface IAuditInfo
{
int CreatedBy { get; set; }
DateTime CreatedDate { get; set; }
int UpdatedBy { get; set; }
DateTime UpdatedDate { get; set; }
}
ISeoFields:
public interface ISeoFields
{
string MetaKeywords { get; set; }
string MetaDescription { get; set; }
string MetaTitle { get; set; }
string UrlAlias { get; set; }
}
产品实体:
public class Product : BaseEntity, IAuditInfo
{
#region "Constructors"
public Product()
{
Translations = new List<ProductTranslation>();
}
#endregion
#region "Properties"
public virtual IList<ProductTranslation> Translations { get; set; }
/******* Implemented from IAuditInfo *******/
public virtual int CreatedBy { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual int UpdatedBy { get; set; }
public virtual DateTime UpdatedDate { get; set; }
/*******************************************/
#endregion
}
产品翻译实体:
public class ProductTranslation : BaseEntity, ISeoFields
{
#region "Constructors"
public ProductTranslation()
{
}
#endregion
#region "Properties"
public virtual Language Language { get; set; }
public virtual Product Product { get; set; }
public virtual string Name { get; set; }
public virtual string ShortName { get; set; }
public virtual string Description { get; set; }
/******* Implemented from ISeoFields *******/
public virtual string MetaKeywords { get; set; }
public virtual string MetaDescription { get; set; }
public virtual string MetaTitle { get; set; }
public virtual string UrlAlias { get; set; }
/*******************************************/
#endregion
}
底图:
public class BaseMap<TEntity, TIdentity> : ClassMap<TEntity> where TEntity : BaseEntity
{
public BaseMap()
{
Id<TIdentity>("Id").GeneratedBy.Identity();
}
}
产品地图:
public class ProductMap : BaseMap<Product, int>
{
public ProductMap()
{
Map(m => m.CreatedBy);
Map(m => m.CreatedDate);
Map(m => m.UpdatedBy);
Map(m => m.UpdatedDate);
HasMany<ProductTranslation>(x => x.Translations).KeyColumns.Add("ProductId").Cascade.All().Inverse();
Table("Product");
}
}
ProductTranslationMap:
public class ProductTranslationMap : BaseMap<ProductTranslation, int>
{
public ProductTranslationMap()
{
Map(m => m.Name);
Map(m => m.ShortName);
Map(m => m.Description);
Map(m => m.MetaKeywords);
Map(m => m.MetaDescription);
Map(m => m.MetaTitle);
Map(m => m.UrlAlias);
References<Language>(r => r.Language, "LanguageId");
References<Product>(r => r.Product, "ProductId");
Table("ProductTranslation");
}
}
我的保存码:
var product = new Product();
product.CreatedBy = 1;
product.CreatedDate = DateTime.Now;
product.UpdatedBy = 1;
product.UpdatedDate = DateTime.Now;
product.Translations = new List<ProductTranslation>() {
new ProductTranslation()
{
Name = "Sony Vaio Notebook",
ShortName = "Sony Vaio Notebook Dizüstübilgisayar",
Description = "Sony Vaio Notebook Dizüstübilgisayar, falan filan test açıklama",
MetaDescription = "Meta Desc Sony Notebook Meta",
MetaKeywords = "Sony,Notebook",
MetaTitle = "Sony Computer",
UrlAlias = "sony-Vaio-notebook",
Language = new Language() {
Culture ="tr-TR",
CurrencyId =1,
FlagImage="tr.png",
Name="Turkish",
Rtl = false
}
},
new ProductTranslation()
{
Name = "ASUS N56VZ Notebook",
ShortName = "ASUS N56VZ Notebook Dizüstübilgisayar",
Description = "ASUS N56VZ Notebook Dizüstübilgisayar, falan filan test açıklama",
MetaDescription = "Meta Desc Asus Notebook Meta",
MetaKeywords = "ASUS,Notebook",
MetaTitle = "ASUS Computer",
UrlAlias = "asus-n56vz-notebook",
Language = new Language() {
Culture ="en-US",
CurrencyId = 2,
FlagImage="en.png",
Name="English",
Rtl = false
}
}
};
Repository.Save(product);
我的问题,
ProductTable
Id | CreatedBy | CreatedDate | UpdatedBy | UpdatedDate
-------------------------------------------------------------------------------
1 | 1 | 2015-03-19 12:42:31.000 | 1 | 2015-03-19 12:42:31.000
LanguageTable
Id | Name | Culture | FlagImage | Rtl | CurrencyId
-------------------------------------------------------------------------------
1 | Turkish | tr-TR | tr.png | 0 | 1
2 | English | en-US | en.png | 0 | 2
Id | Name | ShortName | Description | MetaKeywords |MetaDescription | MetaTitle | UrlAlias | LanguageId | ProductId
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 Sony Vaio Notebook | Sony Vaio Notebook | Dizüstübilgisayar | Sony Vaio Notebook |Dizüstübilgisayar, falan | filan test açıklama | sony-Vaio-notebook | 1 | NULL (Why Null, should be 1)
2 ASUS N56VZ Notebook | ASUS N56VZ Notebook | Dizüstübilgisayar | ASUS N56VZ Notebook |Dizüstübilgisayar, falan | filan test açıklama | asus-n56vz-notebook | 2 | NULL (Why Null, should be 1)
可以看到,LanguageId字段被保存了。但是 ProductId 没有保存在 ProductTranslation table 中。
正常情况下ProductId字段应该为1.
请帮帮我。我的问题在哪里?
你就快完成了,你只需要将 collection 的引用分配给它的项目
var product = new SignECommerce.Domain.Entities.Product();
...
product.Translations = new List<ProductTranslation>();
// child (collection item) gets reference to parent
var item1 = new ProductTranslation()
{
...
Product = product;
},
// now parent is known
var item2 = new ProductTranslation()
{
...
Product = product;
}
// root of that all is now having children
product.Translations.Add(item1);
product.Translations.Add(item2);
// product save will cause all stuff to be properly persisted
Repository.Save(product);
原因是什么?我们正在使用 .Inverse()
映射。那种映射期望:
- 项目 (collection 项目) 将关心持久性并且
- 该物品必须知道其 parent (collection 持有者)
一般来说,对于 ORM/NHibernate,我们应该始终设置两个引用。 Parent 到 child 和 child 到 parent。
当从数据库加载数据时,NHibernate 将为我们设置...在 object(s) 创建期间由我们决定
我的 nhibernate 有问题。
我的代码,
基础实体:
public abstract class BaseEntity : IEntity<BaseEntity, int>, IDisposable
{
public virtual int Id { get; set; }
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
IAuditInfo:
public interface IAuditInfo
{
int CreatedBy { get; set; }
DateTime CreatedDate { get; set; }
int UpdatedBy { get; set; }
DateTime UpdatedDate { get; set; }
}
ISeoFields:
public interface ISeoFields
{
string MetaKeywords { get; set; }
string MetaDescription { get; set; }
string MetaTitle { get; set; }
string UrlAlias { get; set; }
}
产品实体:
public class Product : BaseEntity, IAuditInfo
{
#region "Constructors"
public Product()
{
Translations = new List<ProductTranslation>();
}
#endregion
#region "Properties"
public virtual IList<ProductTranslation> Translations { get; set; }
/******* Implemented from IAuditInfo *******/
public virtual int CreatedBy { get; set; }
public virtual DateTime CreatedDate { get; set; }
public virtual int UpdatedBy { get; set; }
public virtual DateTime UpdatedDate { get; set; }
/*******************************************/
#endregion
}
产品翻译实体:
public class ProductTranslation : BaseEntity, ISeoFields
{
#region "Constructors"
public ProductTranslation()
{
}
#endregion
#region "Properties"
public virtual Language Language { get; set; }
public virtual Product Product { get; set; }
public virtual string Name { get; set; }
public virtual string ShortName { get; set; }
public virtual string Description { get; set; }
/******* Implemented from ISeoFields *******/
public virtual string MetaKeywords { get; set; }
public virtual string MetaDescription { get; set; }
public virtual string MetaTitle { get; set; }
public virtual string UrlAlias { get; set; }
/*******************************************/
#endregion
}
底图:
public class BaseMap<TEntity, TIdentity> : ClassMap<TEntity> where TEntity : BaseEntity
{
public BaseMap()
{
Id<TIdentity>("Id").GeneratedBy.Identity();
}
}
产品地图:
public class ProductMap : BaseMap<Product, int>
{
public ProductMap()
{
Map(m => m.CreatedBy);
Map(m => m.CreatedDate);
Map(m => m.UpdatedBy);
Map(m => m.UpdatedDate);
HasMany<ProductTranslation>(x => x.Translations).KeyColumns.Add("ProductId").Cascade.All().Inverse();
Table("Product");
}
}
ProductTranslationMap:
public class ProductTranslationMap : BaseMap<ProductTranslation, int>
{
public ProductTranslationMap()
{
Map(m => m.Name);
Map(m => m.ShortName);
Map(m => m.Description);
Map(m => m.MetaKeywords);
Map(m => m.MetaDescription);
Map(m => m.MetaTitle);
Map(m => m.UrlAlias);
References<Language>(r => r.Language, "LanguageId");
References<Product>(r => r.Product, "ProductId");
Table("ProductTranslation");
}
}
我的保存码:
var product = new Product();
product.CreatedBy = 1;
product.CreatedDate = DateTime.Now;
product.UpdatedBy = 1;
product.UpdatedDate = DateTime.Now;
product.Translations = new List<ProductTranslation>() {
new ProductTranslation()
{
Name = "Sony Vaio Notebook",
ShortName = "Sony Vaio Notebook Dizüstübilgisayar",
Description = "Sony Vaio Notebook Dizüstübilgisayar, falan filan test açıklama",
MetaDescription = "Meta Desc Sony Notebook Meta",
MetaKeywords = "Sony,Notebook",
MetaTitle = "Sony Computer",
UrlAlias = "sony-Vaio-notebook",
Language = new Language() {
Culture ="tr-TR",
CurrencyId =1,
FlagImage="tr.png",
Name="Turkish",
Rtl = false
}
},
new ProductTranslation()
{
Name = "ASUS N56VZ Notebook",
ShortName = "ASUS N56VZ Notebook Dizüstübilgisayar",
Description = "ASUS N56VZ Notebook Dizüstübilgisayar, falan filan test açıklama",
MetaDescription = "Meta Desc Asus Notebook Meta",
MetaKeywords = "ASUS,Notebook",
MetaTitle = "ASUS Computer",
UrlAlias = "asus-n56vz-notebook",
Language = new Language() {
Culture ="en-US",
CurrencyId = 2,
FlagImage="en.png",
Name="English",
Rtl = false
}
}
};
Repository.Save(product);
我的问题,
ProductTable
Id | CreatedBy | CreatedDate | UpdatedBy | UpdatedDate
-------------------------------------------------------------------------------
1 | 1 | 2015-03-19 12:42:31.000 | 1 | 2015-03-19 12:42:31.000
LanguageTable
Id | Name | Culture | FlagImage | Rtl | CurrencyId
-------------------------------------------------------------------------------
1 | Turkish | tr-TR | tr.png | 0 | 1
2 | English | en-US | en.png | 0 | 2
Id | Name | ShortName | Description | MetaKeywords |MetaDescription | MetaTitle | UrlAlias | LanguageId | ProductId
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 Sony Vaio Notebook | Sony Vaio Notebook | Dizüstübilgisayar | Sony Vaio Notebook |Dizüstübilgisayar, falan | filan test açıklama | sony-Vaio-notebook | 1 | NULL (Why Null, should be 1)
2 ASUS N56VZ Notebook | ASUS N56VZ Notebook | Dizüstübilgisayar | ASUS N56VZ Notebook |Dizüstübilgisayar, falan | filan test açıklama | asus-n56vz-notebook | 2 | NULL (Why Null, should be 1)
可以看到,LanguageId字段被保存了。但是 ProductId 没有保存在 ProductTranslation table 中。 正常情况下ProductId字段应该为1.
请帮帮我。我的问题在哪里?
你就快完成了,你只需要将 collection 的引用分配给它的项目
var product = new SignECommerce.Domain.Entities.Product();
...
product.Translations = new List<ProductTranslation>();
// child (collection item) gets reference to parent
var item1 = new ProductTranslation()
{
...
Product = product;
},
// now parent is known
var item2 = new ProductTranslation()
{
...
Product = product;
}
// root of that all is now having children
product.Translations.Add(item1);
product.Translations.Add(item2);
// product save will cause all stuff to be properly persisted
Repository.Save(product);
原因是什么?我们正在使用 .Inverse()
映射。那种映射期望:
- 项目 (collection 项目) 将关心持久性并且
- 该物品必须知道其 parent (collection 持有者)
一般来说,对于 ORM/NHibernate,我们应该始终设置两个引用。 Parent 到 child 和 child 到 parent。
当从数据库加载数据时,NHibernate 将为我们设置...在 object(s) 创建期间由我们决定