实体框架4.1一对多导航如何防止相关实体的循环加载?
例如:两个表有一对多的关系
event
和discount
每个event
可以有多个discount
s。
当我创建折扣实体对象时,我得到延迟加载的事件对象。 通过事件对象,我可以获得相关折扣的集合并继续循环。
我确信如果这种加载数据很大,性能会降低。
如何在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专辑有流派,然后流派有专辑列表,它继续。它会增加dbcontext的大小或将降低性能。这是处理相关导航属性加载的错误方法吗?
答案 0 :(得分:0)
我们假设我们首先使用实体框架代码。你会有两个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
是一个很棒的免费工具,用于编写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表的子集。