【问题标题】:NHibernate - Question marks instead of values in queryNHibernate - 问号而不是查询中的值
【发布时间】:2015-11-02 10:30:38
【问题描述】:

基本上我有一个Topic 对象,它可以有多个Category 与之关联。我正在尝试将新的Category 插入特定的Topic,但出现错误。

使用 ASP.NET 4 ,在前端使用 windows-1255 编码,在 ASP 和 hebrew_bin 使用 MySQL(后端)

ISession session = dal.GetSession();
using (session.BeginTransaction())
{
    Topic t = session.Get<Topic>(topicId);
    Category c = new Category() { Name=name };
    t.AddCategory(c); // updates both references (inside `t` and inside `c`)
    session.Update(t);
    session.Save(c);
    session.Transaction.Commit();
}

出现错误:

无法插入:[DAL.Models.Category#1][SQL: INSERT INTO Category (Name, Publish, TopicID, ID) VALUES (?, ?, ?, ?)]

最终由于违反外键约束而失败(我猜? 不是有效的ID):

无法添加或更新子行:外键约束失败(etladaatdb.category, CONSTRAINT FK6482F249B6E2851 FOREIGN KEY (ID) REFERENCES topic (ID))

主题.cs:

public enum ColorEnum { Blue, Red, Green, Yellow }
    public class Topic
    {
        public virtual int ID { get; set; }
        public virtual string Name { get; set; }
        public virtual string Description { get; set; }
        public virtual string ImageUri { get; set; }
        public virtual ColorEnum Color { get; set; }

        public virtual IList<Category> Categories { get; set; }

        public virtual void AddCategory(Category c)
        {
            Categories.Add(c);
            c.Topic = this;
        }
    }

主题.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="DAL"
                   namespace="DAL.Models">
  <class name="Topic" lazy="true">
    <id name="ID">
      <generator class="increment"></generator>
    </id>
    <property name="Name" />
    <property name="Description" />
    <property name="ImageUri" />
    <property name="Color" type="ColorEnum" />

    <bag name="Categories" lazy="true" inverse="true"
                         batch-size="25" cascade="all-delete-orphan">
      <key column="ID" />
      <one-to-many class="Category" />
    </bag>
  </class>
</hibernate-mapping>

Category.cs:

public class Category
    {
        public virtual int ID { get; set; }
        public virtual string Name { get; set; }
        public virtual bool Publish { get; set; }

        public virtual Topic Topic { get; set; }
    }

类别.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="DAL"
                   namespace="DAL.Models">
  <class name="Category" lazy="true">
    <id name="ID">
      <generator class="increment"></generator>
    </id>
    <property name="Name"/>
    <property name="Publish" />

    <many-to-one name="Topic" class="Topic" column="TopicID" />
  </class>
</hibernate-mapping>

【问题讨论】:

    标签: c# mysql asp.net nhibernate


    【解决方案1】:

    确实,您似乎错过了将主题分配给类别。所以这应该可以做到这一点:

    // original
    Category c = new Category() { Name=name };
    t.AddCategory(c);
    // always assign both sides during creation
    c.Topic = t;
    

    现在 NHibernate 将知道引用的 Topic 是什么...并且会插入正确的 ID

    关于映射。多对一和一对多的关系正好用一列表示。它是子(类别)表中的外键列 - TopicID。

    所以这是正确的映射:

    // Topic
    <bag name="Categories" lazy="true" inverse="true"
                         batch-size="25" cascade="all-delete-orphan">
      // this is wrong
      // <key column="ID" />
      // this is the target column in the other table
      <key column="TopicID" />
      <one-to-many class="Category" />
    </bag>
    
    ...
    
    // Category
    // the same columns for the same relation
    <many-to-one name="Topic" class="Topic" column="TopicID" />
    

    级联到位后,我们可以保存主题:

    session.Update(t);
    // not needed, there is a cascade
    // session.Save(c);
    

    【讨论】:

    • 观察映射,发现一个问题。关系大约是双方的一列...
    • 检查我的答案 - 包映射需要 &lt;key column="TopicID" /&gt; 而不是原来的 &lt;key column="ID" /&gt;
    • 太棒了,享受强大的 NHibernate,先生 ;)
    【解决方案2】:

    我认为您的实体不完整,您应该更改代码。 不要忘记对IDisposable 对象使用using 语句。

    using(ISession session = dal.GetSession())
    {
    using (session.BeginTransaction())
    {
        Topic t = session.Get<Topic>(topicId);
        Category c = new Category() { Name=name };
        t.AddCategory(c);
        c.Topic = t;
        session.SaveOrUpdate(t);
        session.Transaction.Commit();
    }
    }
    

    你也可以在你的 t.AddCategory(c); 方法中:

    public void AddCategory(Category category)
    {
      // add to list
      category.Topic = this;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-08-12
      • 1970-01-01
      • 2018-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多