1

私はエンティティフレームワーク5を使用しています。エンティティコレクションを遅延ロードしようとしています。モデルを必要最低限​​の部分まで削除して、単純な実行可能なサンプルを作成しました。

これは私のモデルです:

public class A
{

    public int Id { get; set; }

    public EntityCollection<B> Bs
    {
        get { return bs; }
        set { bs = value; }
    }
    private EntityCollection<B> bs;

    public A()
    {
        bs = new EntityCollection<B>();
    }
}

public class B
{
    public int Id { get; set; }
    public A A { get; set; }
}

public class DbModel : DbContext
{
    public DbSet<A> As { get; set; }
    public DbSet<B> Bs { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
                    .HasKey( t => t.Id )
                    .HasMany(a => a.Bs)
                    .WithRequired(b => b.A);
        modelBuilder.Entity<A>()
                    .Property(t => t.Id)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<B>()
                    .HasKey(b => b.Id)
                    .HasRequired(b => b.A);
        modelBuilder.Entity<B>()
                    .Property( t => t.Id )
                    .HasDatabaseGeneratedOption( DatabaseGeneratedOption.Identity );
    }

これは私の問題を示すテストです:

   [TestInitialize]
    public void Initialize()
    {
        model = new DbModel();
        model.Configuration.ProxyCreationEnabled = false;

        if (model.Database.Exists()) model.Database.Delete();

        model.Database.Create();
        A a = model.As.Create();
        model.As.Add(a);
        B b = model.Bs.Create();
        a.Bs.Add(b);

        model.ChangeTracker.DetectChanges();
        model.SaveChanges();
    }

   [TestMethod]
    public void TestMethod1()
    {
        // arrange
        DbModel tModel = new DbModel();
        A a = tModel.As.First();

        // act
        a.Bs.Load();
    }

結果は次のとおりです。

テストメソッドTestProject1.UnitTest1.TestMethod1が例外をスローしました:

System.InvalidOperationException:このRelatedEndの所有者がnullの場合、要求された操作は許可されません。デフォルトのコンストラクターで作成されたRelatedEndオブジェクトは、シリアル化中のコンテナーとしてのみ使用する必要があります。

4

3 に答える 3

1

EntitySetlinq-to-sqlAPIの一部です。これはこの特定の例外を説明するものではありませんが、DbContextとのスムーズな連携に満たないのは当然のことです。DbContext APIを使用する場合、1:nナビゲーションプロパティを次のようなインターフェイスとして定義するのが一般的ですICollection

public virtual ICollection<B> Bs { get; set; }

virtual遅延読み込みのプロキシ作成を有効にするため)

余談ですがmodel.Database.Delete()、データベースが存在するかどうかを確認せずに使用できます。そしてDetectChanges()直前SaveChanges()は冗長です。

于 2012-11-18T22:04:34.573 に答える
0

結局のところ、私はADOファミリーのさまざまなパラダイムのクラスを使用していました。Gert Arnold EFが指摘しているように、EntityCollectionは機能せず、関連付けコレクションにプレーンリストを使用します。

public class A
{

    public int Id { get; set; }

    public List<B> Bs
    {
        get { return bs; }
        set { bs = value; }
    }
    private List<B> bs = new List<B>();
}

プロキシが必要なかったため、オブジェクトにはモデルの「知識」がありません。したがって、モデル自体を使用して、エンティティの関連付けをロードする必要があります。このサンプルでは、​​モデルに次のメソッドを追加しました。

public class DbModel : DbContext
{
    public DbSet<A> As { get; set; }
    public DbSet<B> Bs { get; set; }

//…

    public A LoadAWithAssociations(A targetA)
    {
        return As.Include("Bs").First(a => a.Id.Equals(targetA.Id));
    }
}

新しい方法を使用するようにテストを適応させました

  [TestMethod]
    public void TestMethod1()
    {
        // arrange
        DbModel tModel = new DbModel();
        A a = tModel.As.First();

        // act
        A result =  tModel.LoadAWithAssociations(a);

        // assert 
        Assert.IsNotNull(result);
        Assert.IsTrue(result.Bs.Count > 0);
    }

今はグリーンになります

于 2012-11-25T12:55:53.100 に答える
0

少し複雑な、このコード。クラスAへの参照を含むクラス(B)が本当に必要ですか?クラスAはBのコレクションを持っていますか?わかりにくい名前かもしれませんが、このようなオブジェクトモデルのシナリオは想像できません。

いずれにせよ、私の本能は、循環参照またはオブジェクトプロパティがクラスの1つでインスタンス化されるのを妨げている別の条件を探すことです。

また、a.Bs.Load()を使用したテストメソッドでEagerloadingを使用しています。ProxyCreationEnabled = falseに設定すると、遅延読み込みは無効になります。

于 2012-11-18T19:14:05.327 に答える