2

次のマッピングがあります

UserProfile.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="AngusBook.Domain"
                   namespace="AngusBook.Domain">

  <class name="UserProfile">
    <id name="UserId" type="int">
      <generator class="identity" />
    </id>
    <natural-id mutable="false">
      <property name="UserName" />
    </natural-id>
    <set name="Companies" table="Users_Companies">
      <key column="UserId"/>
      <many-to-many column="CompanyId" class="Company" />
    </set>
  </class>

</hibernate-mapping>

Company.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AngusBook.Domain" namespace="AngusBook.Domain" >

  <class name="Company">
    <id name="Id">
      <generator class="hilo" />
    </id>
    <natural-id mutable="false">
      <property name="CompanyName" />
    </natural-id>
    <set name="Users" table="Users_Companies">
      <key column="CompanyId"/>
      <many-to-many column="UserId" class="UserProfile" />
    </set>
  </class>

</hibernate-mapping>

テーブルデザイン ここに画像の説明を入力

このマッピングを使用すると、Users_Companies テーブルに 2 つの同一の行を作成できます (つまり、UserProfile テーブルと Company テーブルに属する同じ外部キーのペアを持つ 2 つの行)。マッピングを使用して、テーブルに既に存在する Users_Companies に外部キーのペアを挿入しようとしたときに、NHibernate または SQL がエラー/例外をスローするようにするにはどうすればよいですか? Users_Companies の各行は一意であり、反復データを持たないようにしたいと考えています。

4

1 に答える 1

0

私は問題を発見しました。Equals() と GetHashCode() を正しく実装していませんでした。

次の基本エンティティクラスを使用するようにエンティティをリファクタリングすることになり、問題が修正されました。重複したエンティティがセットに追加されてもエラーはスローされませんが、セットは重複したエンティティを追加しません。

Entity.cs public 抽象クラス Entity {

        public virtual TId Id { get; protected set; }
        protected virtual int Version { get; set; }

        public override bool Equals(object obj)
        {
            return Equals(obj as Entity<TId>);
        }

        private static bool IsTransient(Entity<TId> obj)
        {
            return obj != null &&
                   Equals(obj.Id, default(TId));
        }

        private Type GetUnproxiedType()
        {
            return GetType();
        }

        public virtual bool Equals(Entity<TId> other)
        {
            if (other == null)
                return false;

            if (ReferenceEquals(this, other))
                return true;

            if (!IsTransient(this) &&
                !IsTransient(other) &&
                Equals(Id, other.Id))
            {
                var otherType = other.GetUnproxiedType();
                var thisType = GetUnproxiedType();
                return thisType.IsAssignableFrom(otherType) ||
                       otherType.IsAssignableFrom(thisType);
            }

            return false;
        }

        public override int GetHashCode()
        {
            if (Equals(Id, default(TId)))
                return base.GetHashCode();
            return Id.GetHashCode();
        }

    }

    public abstract class Entity : Entity<Guid>
    {

    }

UserProfile.cs

 public class UserProfile : Entity<int>
    {
        public UserProfile()
        {
            Companies = new HashedSet<Company>();
        }

        public virtual string UserName { set; get; }
        public virtual ISet<Company> Companies { set; get; } 
    }

会社.cs

public class Company : Entity<int>
    {
        public Company()
        {
            Users = new HashedSet<UserProfile>();
        }
        public Company(string name) :this()
        {
            this.CompanyName = name;
        }

        public virtual string CompanyName { set; get; }

        public virtual ISet<UserProfile> Users { set; get; }

      }
于 2013-02-07T19:35:34.047 に答える