4

エンティティに複数の関係があり、それらに同時にデータを挿入しようとすると、EF は InvalidCastException をスローします。

例として、次のドメイン クラスを想像してください。

public class Person : Entity<Guid>
{
    public string Name { get; set; }
    public ICollection<Watch> Watches { get; set; }
    public ICollection<Shoe> Shoes { get; set; }
}

public class Shoe : Entity<Guid>
{
    public string Brand { get; set; }
}

public class Watch : Entity<Guid>
{
    public string Brand { get; set; }
}

ユースケース #1 (完璧に動作):

using (var context = new MultipleRelationshipsContext())
{
    var watches =
        new List<Watch>() {
            new Watch { Brand = "Rolex" }
        };

    context.Set<Person>().Add(
        new Person
        {
            Name = "Warren Buffett",
            Watches = watches
        }
    );
}

使用例 #2 (これも完璧に機能します):

using (var context = new MultipleRelationshipsContext())
{
    var shoes =
        new List<Shoe>() {
            new Shoe { Brand = "Cole Haan" }
        };

    context.Set<Person>().Add(
        new Person
        {
            Name = "Barack Obama",
            Shoes = shoes
        }
    );
}

使用例 #3 (InvalidCastException):

using (var context = new MultipleRelationshipsContext())
{
    var watches =
        new List<Watch>() {
            new Watch { Brand = "Casio" }
        };

    var shoes =
        new List<Shoe>() {
            new Shoe { Brand = "New Balance" }
        };

    context.Set<Person>().Add(
        new Person
        {
            Name = "Steve Jobs",
            Watches = watches,
            Shoes = shoes
        }
    );
}

EntityFrameworkMultipleRelationships.Entities.Watch3 番目のケースでは、EF が 'から ' ' にキャストできないことを示す InvalidCastException がスローされEntityFrameworkMultipleRelationships.Entities.Shoeます。

私は EF の初心者ですが、ここで何か問題が発生していると思います。

可能な解決策を指摘するヒントをいただければ幸いです。

PD .: できるだけ早く自分自身をテストするには、次の VS2012 ソリューションをダウンロードしてください: https://dl.dropboxusercontent.com/u/22887057/EntityFrameworkMultipleRelationships.zip。README.txt に従って、コード ファースト パターンに従ってデータベースを作成します。

アップデート

@Chris が指摘したように、問題は、EF が靴と時計のエンティティを同じと見なすことでした。これは、不適切に実装されたオーバーライドされた Equals が原因でした。これが実際に問題の原因です。

public abstract class Entity<T>
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column("Id")]
    public T Id { get; set; }

    public override bool Equals(object obj)
    {
        Entity<T> entityOfT = obj as Entity<T>;
        if (entityOfT == null)
            return false;

        return object.Equals(this.Id, entityOfT.Id);
    }

    public override int GetHashCode()
    {
        return this.Id.GetHashCode();
    }
}

2 つの異なるエンティティ タイプ (Watchと などShoe) の ID が同じ場合、EF はそれらを等しいと見なします。

オーバーライドされた Equals にランタイム タイプ チェックを追加すると、エンティティ タイプが考慮されるため、この問題が解決されます。

...
return this.GetType() == entityOfT.GetType() && object.Equals(this.Id, entityOfT.Id);
...
4

2 に答える 2

1

その特定のエラーがスローされる理由はわかりませんが、Entity.Id 定義のために EF が混乱しているようです。PK フィールドを Shoe および Watch クラス定義に移動すると、機能します。また、コレクションを介して Person オブジェクトに追加する前に、時計と靴のオブジェクトをそれぞれの DbContext セットに追加すると、それも機能します。いずれにせよ、何らかの方法でもう少し明確にすることで、問題は解決します。

于 2013-08-12T13:38:53.417 に答える