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) 创建期间由我们决定