0

私は、SQLで2分でできることを実行できるように、最初にEFコードを取得しようとしている大失敗です。それを機能させるためにまだ5日間を費やしていなければ、データベースをDDLでコーディングし、ADO.NETを使用するだけでした。しかし、私は逸脱します...

Aの各レコードにBの対応するレコードがある、2つのテーブルが必要です。これらは両方とも同じオブジェクトの一部です。私が入らない理由で、それらは別々のテーブルにある必要があります(しかし、実際にはそうなので、そこには行かないでください)。データベース側から設計する場合は、BからAへのFK関係があります。ジョブは完了です。

EF Code Firstでは、共有主キー方式1対1の外部キー関連付け方式の両方を使用しようとしましたが、どちらも機能しません。私はまた、私が考えることができるすべての変種の100かそこらの組み合わせを試しました、そして私はそれ以上前進しません。

私が言ったように、私が望んでいるのは、AからBへのナビゲート可能な関係があり(そして戻るのは良いことですが、それは不可能だと読んだことがあります)、その関係が遅延ロードされることです。a.bbのフィールドにアクセスできます。

私が試したすべてのことを列挙することはおそらくできないので、ほとんど機能するものの例を挙げましょう。

class Foo
{
    public int Id { get; set; }
    public string FooProperty { get; set; }

    public virtual Bar Bar { get; set; }
}

class Bar
{
    public int Id { get; set; }
    public string BarProperty { get; set; }
}

(a)SQL Serverは複数のカスケード削除パスについて文句を言い、(b)EFはどちらの側が関連付けの主要な端であるかわからないことについて文句を言うので、BarからFooへの逆参照がないことに注意してください。だから...大丈夫-私はそれなしで生きることができます。

これがデータベースで私を取得するのは、とフィールドを持つテーブルFoosIdFooPropertyBar_Idフィールドを持つBarsテーブルです。これは、SQLでモデル化する方法にかなり近いものですが、おそらくFKフィールドをではなく入力するでしょう。しかし、1:1なので、それほど重要ではないと思います。IdBarPropertyBarFoo

これがほぼ機能すると言う理由は、とを追加してBarからFooそれらを再度ロードするとBar、オブジェクトのプロパティFooがnullになるためです。

using (var dbContext = new MyDbContext())
{
    var foo = dbContext.Foos.Create();
    foo.FooProperty = "Hello";
    dbContext.Foos.Add(foo);

    var bar = dbContext.Bars.Create();
    bar.BarProperty = "world";

    foo.Bar = bar;

    dbContext.SaveChanges();
}

using (var dbContext = new MyDbContext())
{
    foreach (var foo in dbContext.Foos)
        Console.WriteLine(foo.Bar.Id); // BOOM! foo.Bar is null
}

foo.Bar通常、の評価がオブジェクトの遅延読み込みをトリガーすることを期待しBarますが、そうではありません-そのプロパティは残りnullます。

どうすれば修正できますか?

4

4 に答える 4

3

これはうまくいくはずです:

環境

public class FoobarCtx : DbContext
{
    public DbSet<Bar> Bars { get; set; }
    public DbSet<Foo> Foos { get; set; }

    public FoobarCtx()
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Bar>()
            .HasRequired(f => f.Foo)
            .WithRequiredDependent(b => b.Bar)
            .Map(x => x.MapKey("FooId"))
            .WillCascadeOnDelete(true);
    }
}

エンティティ

public class Foo
{
    public int Id { get; set; }

    public string Foo1 { get; set; }
    public string Foo2 { get; set; }

    public virtual Bar Bar { get; set; }
}

public class Bar
{
    public int Id { get; set; }
    public string Bar1 { get; set; }
    public string Bar2 { get; set; }

    public virtual Foo Foo { get; set; }
}

EF 4.3 でテストしましたが、EF5 でも動作するはずです。キーはOnModelCreatingメソッドです。そこで、どちらか一方をプリンシパル/子孫として定義し、Microsoft SQL の制限を取り除くことができます。

詳細については、このブログ投稿を参照してください。モデル ビルダー (流暢な API) の詳細については、こちらを参照してください。

遅延読み込みを有効にするには、DbContext.FooSet.Create() メソッドを使用します。例はこちら

于 2012-08-06T21:04:19.180 に答える
0

私自身へのリマインダーとして、他に何もないとしても...

LueTmは、私が最初に考えていたテーブル構造(BarテーブルのFooId列を使用)と、2つのテーブルの独立したPKを生成するソリューションに到達しました。を使用して最初にロードせずにFoo.BarプロパティにアクセスすることはまだできませんでしたdbContext.Foos.Include(f => f.Bar)

また、共有主キーを使用して物事をうまく機能させることができました(両方のテーブルにPKがありますが、Foosの1つだけがID(自動インクリメント)列であり、バーのIDからFoosのID。

これを行うために、FooクラスにBarプロパティを、BarクラスにFooプロパティを設定し(双方向ナビゲーションが機能するように)、OnModelCreatingに次のように配置しました。

modelBuilder.Entity<Bar>()
                .HasRequired(x => x.Foo)
                .WithRequiredDependent(x => x.Bar)
                .WillCascadeOnDelete(true);

modelBuilder.Entity<Foo>()
                .HasRequired(x => x.Bar)
                .WithRequiredPrincipal(x => x.Foo)
                .WillCascadeOnDelete(true);

(ここでの2番目の呼び出しが実際に何かを行うかどうかはわかりません)。

ただし、Include()にアクセスできるようにするには、まだ呼び出しが必要ですfoo.Bar

于 2012-08-06T22:33:02.530 に答える
0

私はこれを自分で経験しました。FoodEntryとFoodがあり、FoodにはFoodGroupがあります。

public class FoodEntry
{
    public int      Id { get; set; }
    public string   User { get; set; }
    public Food     Food { get; set; }
    public decimal  PortionSize { get; set; }
    public Portion  Portion { get; set; }
    public int      Calories { get; set; }
    public Meal  Meal { get; set; }
    public DateTime? TimeAte { get; set; }
    public DateTime EntryDate { get; set; }
}

public class Food
{
    public int       Id { get; set; }
    public string    Name { get; set; }
    public FoodGroup FoodGroup { get; set; }
}

public class FoodGroup
{
    public int Id { get; set; }
    public string Name { get; set; }
}

私は最初にコードを使用しており、私のPOCOクラスはあなたと同じように定義されています。仮想とマークされたプロパティがありません。

いずれにせよ、データベースは私が期待するように、あなたが説明したように外部キーを使って生成します。

しかし、このクエリの結果、Food、Portion、およびMealプロパティにnullが含まれるFoodEntryコレクションが取得されました。

var foodEntries = db.FoodEntries
            .Where(e => e.User == User.Identity.Name).ToList();

クエリをこれに変更し、グラフ全体をコレクションにロードしました。

var foodEntries = db.FoodEntries
            .Include( p => p.Food)
            .Include(p => p.Food.FoodGroup)
            .Include(p => p.Portion)
            .Include( p => p.Meal)
            .Where(e => e.User == User.Identity.Name).ToList()
            ;
于 2012-08-20T03:20:38.140 に答える
0

1:many の関係に加えて1:1の関係の場合(Foo には複数の Bar と CurrentBar があります):

        modelBuilder.Entity<Foo>()
            .HasOptional(f => f.CurrentBar)
            .WithMany()
            .HasForeignKey(f => f.CurrentBarId);

        modelBuilder.Entity<Bar>()
            .HasRequired(b => b.Foo)
            .WithMany(f => f.Bars)
            .HasForeignKey(b => b.FooId);
于 2013-12-11T14:42:32.030 に答える