0

1対多のナビゲーションを備えたエンティティフレームワーク4.1関連エンティティの循環ロードを防ぐ方法?

例: 2 つのテーブルには 1 対多の関係があります

eventdiscount

それぞれeventに複数discountの を含めることができます。

ディスカウント エンティティ オブジェクトを作成すると、イベントのオブジェクトが遅延読み込みで取得されます。イベント オブジェクトを使用して、関連する割引のコレクションを取得し、サイクルを続けます。

この種のロードでデータが大きい場合、パフォーマンスが低下すると確信しています。

Entityフレームワークでそのような状況を処理する方法。

public Event()
{
  public virtual ICollection<discount> discounts{ get; set; }    
}

public Discount
{    
  public virtual Event Event {get;set;}    
}

別の例:

 [Bind(Exclude = "AlbumId")]
public class Album
  {
    [ScaffoldColumn(false)]
    public int AlbumId { get; set; }

    [DisplayName("Genre")]
    public int GenreId { get; set; }

    public virtual Genre Genre { get; set; }        

  }


   public partial class Genre
  {
    public int GenreId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public List<Album> Albums { get; set; }
  }


 public ViewResult Index()
        {
            var albums = db.Albums.Include(a => a.Genre).Include(a => a.Artist);
            return View(albums.ToList());
        }



   @foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Genre.Name)
        </td>
        <td>
            @Truncate(item.Artist.Name, 25)
        </td>
        <td>
            @Truncate(item.Title, 25)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.AlbumId }) |
            @Html.ActionLink("Details", "Details", new { id=item.AlbumId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.AlbumId })
        </td>
    </tr>
   }

上記の例で。アルバムにはジャンルが含まれています。したがって、アルバムにはジャンルがあり、ジャンルにはアルバム リストがあり、それが続きます。dbcontext のサイズが大きくなったり、パフォーマンスが低下したりします。これは、関連するナビゲーション プロパティの読み込みを処理する間違った方法ですか?

4

1 に答える 1

0

最初に Entity Framework コードを使用していると仮定しましょう。2 つの POCO クラスがあります。同じ名前のテーブルにマップされるイベントと割引。

public class Event
{
    public Event()
    {
        this.Discounts = new HashSet<Discount>();
    }

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

    public virtual ICollection<Discount> Discounts { get; set; }
}

public class Discount
{
    public int Id { get; set; }
    public decimal Amount { get; set; }

    public int EventId { get; set; }
    public virtual Event Event { get; set; }

}

そして、DBContextから継承するクラスがあります

public class ExampleContext: DbContext
{
    public DbSet<Event> Events { get; set; }
    public DbSet<Discount> Discount { get: set; }
}

EventId = 1 のイベントごとに割引にアクセスするには

var db = new ExampleContext();

var discounts = db.Discounts.Where(d => d.EventId == 1);

イベント オブジェクトがある場合は、次のようにイベントごとの割引にアクセスできます。

var event = db.Events.FirstOrDefault(e => e.Id == 1);

var discount = db.Entry(discount).Reference(d => d.Event).Load();

同様のアプローチをとれば、エンティティの循環ロードに問題はないと思います。これが役立つことを願っています!

編集:ジャンルとアルバムを使用したコードの最初のアプローチは正しいようです。POCO クラスと DbContext クラスを正しく設定したと仮定すると、パフォーマンスは LINQ クエリの書き方によって決まります。優れた LINQ クエリは、優れた SQL コードを生成します。不適切な LINQ クエリは、不適切な SQL コードを生成します。LINQパッド

http://www.linqpad.net

は、linq クエリを作成し、生成された SQL コードとクエリの結果を調べるための素晴らしい無料ツールです。例えば

var albums = db.Albums;

に相当するものを生成します

SELECT * FROM Albums;

エンティティまたはテーブルのすべてのレコードを返すことはめったにありません。一方で

var albums = db.Albums.Where(a => a.GenreId == 1).ToList();

のようなものを生成します

SELECT * FROM Albums
WHERE GenreId = 1;

Albums テーブルのサブセットのみを返します。

于 2013-06-04T13:42:15.617 に答える