【问题标题】:Fluent Nhibernate save child.parentid = parentId on new parent & ChildFluent Nhibernate save child.parentid = parentId on new parent & Child
【发布时间】:2013-12-13 20:59:22
【问题描述】:

我正在尝试将新的父项和新的子项保存到旧数据库中

我的数据很好,当我保存它时会同时保存父母和孩子。但是 Child 的 SillyNameParentId 始终为 0

我无法更改表结构,因此我必须弄清楚如何进行这项工作。

这里是生成的 SQL

NHibernate:INSERT INTO SillyNameParent(描述,活动)值 (@p0,@p1);选择 SCOPE_IDENTITY();@p0 = 'Test' [类型:字符串 (1073741823)], @p1 = True [类型:布尔 (0)] NHibernate:插入 SillyChild (SillyNameCategoryId, sillyNameParentid) 值 (@p0, @p1); 选择 SCOPE_IDENTITY();@p0 = 0 [类型:Int32 (0)],@p1 = 1 [类型: Int32 (0)]

最终我希望将@p1 设置为 SillyNameParentId/Parentid

表格:

SillyNameParent
    Column PK-IsIdentity: ParentId
    Column varchar(255): Description
    Column bit: Active

SillyChild //I'm a lookup table 
    Column int IsIdentity: Id
    Column int PK: SillyNameParentId
    Column int PK: SillyNameCategoryID

型号:

public class SillyNameParent: Entity
{
    public SillyNameParent()
    {
        Children= new List<SillyChild>();
    }
    public virtual string AreaOfConcernDesc { get; set; }
    public virtual bool Active { get; set; }
    public virtual IList<SillyChild> Children{ get; set; }
}

public class SillyChild: Entity
{
    public virtual int SillyNameParentId { get; set; }
    public virtual int SillyNameCategoryId{ get; set; }
    public virtual SillyNameParent Parent { get; set; }

}

地图:

public class SillyNameParentMap : IAutoMappingOverride<SillyNameParent>
{
    public void Override(AutoMapping<SillyNameParent> mapping)
    {
        mapping.Table("SillyNameParent");
        mapping.Id(x => x.Id).Column("ParentId").GeneratedBy.Identity();
        mapping.Map(x => x.Description).Not.Nullable();
        mapping.Map(x => x.Active).Nullable();
        mapping.HasMany(x => x.children)
            .Cascade.All()
            .KeyColumn("SillyNameParentId")
            .Not
            .LazyLoad();
    }
}

public class SillyChildMap: IAutoMappingOverride<SillyChild>
{
    public void Override(AutoMapping<SillyChild> mapping)
    {
        mapping.Table("SillyChild");
        mapping.Id(x => x.Id).Column("Id").GeneratedBy.Identity();
        mapping.Map(x => x.SillyNameParentId).Not.Nullable();
        mapping.Map(x => x.SillyNameCategoryId).Not.Nullable();
        mapping.HasOne(x => x.Parent).ForeignKey("SillyNameParentId");
    }
}

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate


    【解决方案1】:

    我想说,你快到了。只是映射父/子应该是这样的:

    SillyNameParentMap:

    public void Override(AutoMapping<SillyNameParent> mapping)
    {
        ...
        mapping.HasMany(x => x.Children)
            .Cascade.All()
            .KeyColumn("SillyNameParentId")
            .Inverse() // this is the way how to manage insertions
            .Not
            .LazyLoad();   
    

    傻孩子地图:

    public void Override(AutoMapping<SillyChild> mapping)
    {
        ...
        mapping.References(x => x.Parent)
           .Column("SillyNameParentId");
    

    这个映射最终会正确插入,只需这样做:

    var parent = new SillyNameParent();
    parent... // set properties
    
    var child = new SillyChild();
    child... // set properties
    
    parent.Children.Add(child); // parent knows about child
    child.Parent = parent; // always do set the relation both ways
    
    sillyService.SaveSillyParent(snp)
    

    编辑:选择 2 问题

    例外情况是双列映射。这是 INSERT 或 UPDATE 的问题。但是使用 NHibernate 我们可以轻松解决它:

    mapping.Map(x => x.SillyNameParentId)
        .Not.Nullable()
        .Not.Insert()
        .Not.Update();
    mapping.References(x => x.Parent)
        .Column("SillyNameParentId");
    

    所以,现在我们已经映射了两个属性(引用 Parent 及其 int 表示)。只有引用将用于 INSERT、UPDATE。但两者都可以用于 Select、Filter/Where 和 Order by...

    【讨论】:

    • 我实际上已经尝试过了,但没有成功,当 sillyChild 使用映射时,我收到此错误:...Parent 的错误脱水属性值,InnerException:Invalid index 2 for this SqlParameterCollection with Count =2.
    • 我看不到错误?这是你评论的一部分吗?父子关系很平常。最常见的。它确实可以在没有“解决方法”的情况下工作。请提供更多信息..我们会找到解决方案。哇……我​​明白了。我会在一个小时内回来……看看
    • 是的,我同意这是一种非常普遍的关系,我经常使用这种模式。但是我在想,因为这个数据库是遗留的,并且父表 ID 列的命名不同于引用父名称列的子查找表列,再加上数据库设置标识可能是模式不起作用的原因。感谢您的帖子,并提前感谢您进一步调查
    • 我已经更新了我的答案。为了解决这个问题,我们只需要确保每列仅映射一次以用于 INSERT 和 UPDATE。现在我们应该拥有所有标准的东西。顺便说一句,我经常使用这种方式......非常方便;)
    • 太完美了!谢谢!
    【解决方案2】:

    这是一个解决方法...因为身份是由数据库设置的,所以我猜我需要先保存父级,然后再保存子级。必须有更好的方法,但这就是我想出的

     public T SaveReturnEntity(T entity)
        {
            try
            {
                this.Session.Save(entity);
            }
            catch
            {
                if (this.Session.IsOpen)
                {
                    this.Session.Close();
                }
    
                throw;
            }
    
            this.Session.Flush();
            return entity;
        }
    
    
    
     return _sillyParent.SaveReturnEntity(sillyNameParent) != null;
    
    
     [Test]
        public void Save_sillyParent()
        {
            var sillyService = ServiceMiniMart.CreateSillyParent();
    
            var filter = new sillyQueryFilter();
            {
                CategoryId = 1
            };      
            var snp= new SillyNameParent
                {
                    Active = true,
                    Description= "Test"
                };
            if (sillyService.SaveSillyParent(snp))
            {
               snp.Category = new List<SillyChild>
                   {
                       new SillyChild
                           {
                               SillyNameParentId= snp.Id,
                               SillyNameCategoryId= filter.CategoryId.Value,
                               Parent = snp
                           }
                   };
            }
    
    
           var a =  sillyService.SaveSillyParent(snp);
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-14
      • 2011-04-15
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多