2013-06-04 1 views
0

Entity framework 4.1 с навигацией по многим причинам, как предотвратить циклическую загрузку связанных объектов?Entity framework 4.1 с одним-многим навигационным способом, как предотвратить циклическую загрузку связанных объектов?

Ex: Две таблицы имеют один ко многим отношению

event и discount

Каждый 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> 
    } 

В выше отл. Альбомы включали Genre.So Album, есть жанр, а затем жанр имеет список альбомов, и он продолжается. Будут увеличены размеры dbcontext или снизятся производительность. Это неправильный способ справиться с загрузкой связанных свойств навигации?

ответ

0

Предположим, что мы сначала используем код Entity Framework. У вас будет два класса 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. LINQPad

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.

+0

Спасибо @ wayne.blackmon! Если нам нужно отключить ленивую загрузку для этого в DbContext как «Configuration.LazyLoadingEnabled = false;», а также нам нужно удалить Virtual из свойств, показанных выше? – SNJ

+0

Вы должны пометить все свойства ассоциации как виртуальные. Я не думаю, что ленивая загрузка - это проблема. Мне нужно будет увидеть ваш код linq, чтобы узнать, в чем проблема. Я предпочитаю не перемещать свойства ассоциации в коде LINQ. Каждый раз, когда вы нажмете один, он будет заполняться. Попробуйте использовать идентификатор записи или другие критерии в вашем лямбда-выражении, как показано выше. –

+0

В приведенном выше примере. Альбомы включали Genre.So Album, есть жанр, а затем жанр имеет список альбомов, и он продолжается. Будут увеличены размеры dbcontext или снизятся производительность. Это неправильный способ справиться с загрузкой связанных свойств навигации? – SNJ