Nhibernate OneToMany(Inverse)将FK设置为​​0,为什么?

时间:2014-10-27 13:02:40

标签: c# nhibernate nhibernate-mapping mapping-by-code

我的nHibernate Mapping-By-Code有一个问题。

Content包含FK列“ContentId”引用的表Content_Texts中的多个条目。

如果我在集合中添加一个带有一个Text的新ContentEntry,我将获得对内容表执行的第一个查询,但第二个查询(对于Content_Texts)失败,因为NHibernate正在尝试插入Content_Text实体 ContentId = 0 ,在内容表中确实不存在。

这是我的内容表映射:

public class ContentMap : ClassMapping<TContent>
{
    #region Constructors

    public ContentMap()
    {
        Table("nfcms_Content");
        Schema("dbo");
        Lazy(false);
        Id<int>(x => x.Id, map => {

            map.Generator(Generators.Identity);

        });
        //Property(x => x.Id, map => map.NotNullable(true));

        Property(x => x.Cid, map =>
        {
            map.NotNullable(false);

        });
        Property(x => x.CreatorPKID, map => map.NotNullable(false));
        Property(x => x.Locked, map => {

            map.NotNullable(true);

            map.Type(NHibernateUtil.Boolean);

        });
        Property(x => x.RatingGroupID);
        Property(x => x.CDate);

        Property(x => x.ContentType, map => map.NotNullable(true));

        Property(x => x.ContentRef);
        Property(x => x.CreatorSpecialName);

        Bag(x => x.Texts, mapping =>
        {
            mapping.Lazy(CollectionLazy.NoLazy);
            mapping.Key(k =>
            {
                k.Column("ContentId");

            });
            mapping.Inverse(true);
            mapping.Cascade(Cascade.All);

            mapping.Fetch(CollectionFetchMode.Select);

        },
           r => r.OneToMany());

        ManyToOne(x => x.User, m =>
        {

            m.Column(c => c.Name("CreatorPKID"));
            m.Fetch(FetchKind.Select);
            m.Cascade(Cascade.None);
            m.Insert(false);
            m.Update(false);
            m.Lazy(LazyRelation.NoLazy);

        });

        ManyToOne(x => x.Category, m =>
        {

            m.Column(c => c.Name("CID"));
            m.Fetch(FetchKind.Select);
            m.Cascade(Cascade.None);
            m.Insert(false);
            m.Update(false);
            m.Lazy(LazyRelation.NoLazy);

        });

        //OneToOne(x => x.Category, map =>
        //{
        //    map.PropertyReference(
        //    map.Column("CID");
        //    map.NotFound(NotFoundMode.Ignore);
        //    map.Cascade(Cascade.None);
        //});

        //ManyToOne(x => x.User, map =>
        //{
        //    map.PropertyRef("PKID");
        //    map.Column("CreatorPKID");

        //    map.Cascade(Cascade.None);
        //});
    }

    #endregion Constructors
}

这里是Content_Text表

public class ContentTextMap : ClassMapping<Persistence.Domain.ContentText>
{
    #region Constructors

    public ContentTextMap()
    {
        Table(Ren.CMS.CORE.Config.RenConfig.DB.Prefix +"Content_Text");
        Schema("dbo");
        Lazy(false);
        Id<int>(x => x.Id, map => {

            map.Generator(Generators.Identity);

        });
        Property(x => x.ContentId, map => map.NotNullable(true));
        Property(x => x.LangCode, map => map.NotNullable(true));

        //Property(x => x.Id, map => map.NotNullable(true));
        Property(x => x.Title, map => map.NotNullable(true));

        Property(x => x.Seoname);

        Property(x => x.MetaKeyWords);
        Property(x => x.MetaDescription);
        Property(x => x.PreviewText);

        Property(x => x.LongText, x => x.Type(NHibernateUtil.StringClob));


        //OneToOne(x => x.Category, map =>
        //{
        //    map.PropertyReference(
        //    map.Column("CID");
        //    map.NotFound(NotFoundMode.Ignore);
        //    map.Cascade(Cascade.None);
        //});

        //ManyToOne(x => x.User, map =>
        //{
        //    map.PropertyRef("PKID");
        //    map.Column("CreatorPKID");

        //    map.Cascade(Cascade.None);
        //});
    }

    #endregion Constructors
}

这是NHibernate执行的查询:

  

NHibernate:INSERT INTO dbo.nfcms_Content(CDate,Cid,ContentRef,ContentType,CreatorPKID,CreatorSpecialName,Locked,RatingGroupID)VALUES(@ p0,@ p1,@ p2,@ p3,@ p4,@ p5,@ p6, @ P7); select SCOPE_IDENTITY(); @ p0 = 27.10.2014 13:51:58 [Type:DateTime(0)],@ p1 = NULL [Type:Guid(0)],@ p2 = 0 [Type:Int32(0)] ,@ p3 ='eNews'[Type:String(4000)],@ p4 = NULL [Type:Guid(0)],@ p5 =''[Type:String(4000)],@ p6 = False [类型:布尔值(0)],@ p7 = 0 [类型:Int32(0)]

     

NHibernate:INSERT INTO dbo.nfcms_Content_Text(ContentId,LangCode,LongText,   MetaDescription,MetaKeyWords,PreviewText,Seoname,Title)VALUES(@ p0,@ p1,@ p2,@ p3,@ p4,@ p5,@ p6,@ p7); select SCOPE_IDENTITY(); @ p0 = 0 [Type:Int32(0)],@ p1 ='de-DE'[Type:String(4000)],@ p2 ='Test'[Type:String(1073741823)], @ p3 ='test'[Type:String(4000)],@ p4 ='test'[Type:String(4000)],@ p5 ='test'[Type:String(4000)],@ p6 ='TEST123455 '[Type:String(4000)],@ p7 ='TEST'[Type:String(4000)]

谁能告诉我什么是错的?我搜查了一下,没有找到任何污垢......

1 个答案:

答案 0 :(得分:0)

因为我们确实将one-to-many关系结束映射为Bag,其中反向设置(这绝对没问题),如下所示:

public ContentMap()
{
    ...
    Bag(x => x.Texts, mapping =>
    {
        mapping.Lazy(CollectionLazy.NoLazy);
        mapping.Key(k =>
        {
            k.Column("ContentId");

        });
        ...

我们需要另一端 - 多对一。在我们的情况下,必须由引用 Content 表示(并且也可以表示为只读int ContentId 价值)

public ContentTextMap()
{
    ManyToOne(x => x.Content, "ContentId");
    Property(x => x.ContentId, map => {
        map.Column("ContentId");
        map.Update(true);
        map.Insert(true);
        map.NotNullable(true)
    });
    ...

期待 POCO 是这样的:

public class Content
{
   public virtual IList<ContentText> Texts { get; set; }
   ...

public class ContentText
{
   public virtual Content Content { get; set; }
   public virtual int ContentId { get; set; }
   ...

这必须是作业(必须分配两端)

var content = ...;
var contentText = ...;
content.Texts.Add(contentText);// both ends must be assigned
contentText.Content = content; // both ends must be assigned