概述
我首先使用实体框架4.3代码和fluent接口来设置我的DbContext。我有一个基项类,它具有继承此类的其他类型,例如事件、BlogPost、ForumThread、WikiPage等等。
这些继承类型与我认为实体框架所指的TPT继承相映射。这在查询单个类型(如“events”或“blog post”)时非常有用,但在尝试跨所有类型查询时,会构造非常复杂的查询,性能非常糟糕,因为为了实现EF提供的多态行为而需要连接。
问题上下文
我想要构建一个全局搜索功能,我只需要访问基“Item”实体,而不需要访问继承的实例。我希望能够通过名称、标记等对基项类进行查询。执行任何类型的LINQ查询,即使在请求基项类型时,仍然会导致多态行为,从而降低性能。
码第一模型
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Body { get; set; }
public DateTime Created { get; set; }
public int? CreatedBy { get; set; }
public int? LastModifiedBy { get; set; }
public DateTime? LastModified { get; set; }
public virtual User Author { get; set; }
public bool IsDeleted { get; set; }
public string ImageUri { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
public class Event : Item
{
// Additional properties
}
public class BlogPost : Item
{
// Additional properties
}我想要做的是将另一个POCO映射到同一个基表,这样当我在它上构造查询时,它就不会涉及继承问题。不过EF似乎不喜欢这样。目前我手头上没有错误,但我在简单映射方面的尝试失败了。
替代解决方案?
我最喜欢的解决方案是在代码中,而不是数据库触发器/存储过程中。
是否有一种方法来构造查询以强制EF只返回基类型而不是多态类型,这会导致太多的连接和糟糕的性能?还是有其他聪明的方法来解决这个问题?
更新
在通过Nuget (针对EntityFramework 4.0)更新到.Net 5之后,我已经能够通过它们的标记查询条目,并将其投影到一个新的SearchItem中,这将产生相当干净的SearchItem,而无需加入TPT类型。
var x = from item in repository.FindAll<Item>()
where item.Tags.Any(t => t.Name == "test")
select new SearchItem
{
Id = item.Id,
Name = item.Name,
Body = item.Body,
Created = item.Created,
CreatedBy = item.CreatedBy,
IsDeleted = item.IsDeleted,
ImageUri = item.ImageUri,
MembershipEntityId = item.MembershipEntityId,
//Tags = (from t in item.Tags
// select new Tag
// {
// Id = t.Id,
// Name = t.Name,
// MembershipEntityId = t.MembershipEntityId
// })
};SQL
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Body] AS [Body],
[Extent1].[Created] AS [Created],
[Extent1].[CreatedBy] AS [CreatedBy],
[Extent1].[IsDeleted] AS [IsDeleted],
[Extent1].[ImageUri] AS [ImageUri],
[Extent1].[MembershipEntityId] AS [MembershipEntityId]
FROM [dbo].[Item] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM [dbo].[ItemTag] AS [Extent2]
INNER JOIN [dbo].[Tag] AS [Extent3] ON [Extent3].[Id] = [Extent2].[Tag_Id]
WHERE ([Extent1].[Id] = [Extent2].[Item_Id]) AND (N'test' = [Extent3].[Name])
)这已经解决了我的一半的问题,因为我现在可以搜索的基础类型的标签。然而,我希望能够返回标记与新的投影。包括注释掉的代码会导致一个EF无法翻译的查询。有办法解决这个问题吗?
发布于 2012-12-05 13:10:07
是否有一种方法来构造查询以强制EF只返回基类型而不是多态类型,这会导致太多的连接和糟糕的性能?
一般不会。您已经映射了继承,如果要返回Item的实例,EF必须始终返回正确的类型=>,它需要这些联接。EF也不允许多次映射相同的表,因此您不能在同一映射中将Item再次映射为另一个POCO。
理论上,您应该能够将Items和项目查询到您的非映射 POCO类,只需从基类中获取您想要的属性。不幸的是,这在.NET 4.0 - EF仍然执行连接中行不通。您可以在.NET 4.5和EF5.0中尝试这一点,其中问题是应该解决。
https://stackoverflow.com/questions/13722780
复制相似问题