我使用实体框架连接数据库。我有个小问题
我有一个表,其中有一个varbinary(MAX)列(带有filestream)。
我使用SQL请求来管理“数据”部分,但EF用于其余部分(文件的元数据)。
我有一个代码,必须得到所有的文件ID,文件名,GUID,修改日期,...这完全不需要“数据”字段。
有没有一种方法来检索一个列表,但没有填写此列?
就像
context.Files.Where(f=>f.xyz).Exclude(f=>f.Data).ToList();
??
我知道我可以创建匿名对象,但我需要将结果传输给一个方法,所以没有匿名方法。我不想把它放在匿名类型的列表中,然后创建一个非匿名类型的列表(文件)。
我们的目标是避免这种情况:
using(RsSolutionsEntities context = new RsSolutionsEntities())
{
var file = context.Files
.Where(f => f.Id == idFile)
.Select(f => new {
f.Id, f.MimeType, f.Size, f.FileName, f.DataType,
f.DateModification, f.FileId
}).FirstOrDefault();
return new File() {
DataType = file.DataType, DateModification = file.DateModification,
FileId = file.FileId, FileName = file.FileName, Id = file.Id,
MimeType = file.MimeType, Size = file.Size
};
}
(我在这里使用匿名类型,因为否则你会得到一个NotSupportedException:不能在LINQ to Entities查询中构造实体或复杂类型“ProjectName.File”。)
(e.g.这段代码抛出前面的异常:
File file2 = context.Files.Where(f => f.Id == idFile)
.Select(f => new File() {Id = f.Id, DataType = f.DataType}).FirstOrDefault();
而“File”是我用context.Files.ToList()
得到的类型。这是一个很好的类:
using File = MyProjectNamespace.Common.Data.DataModel.File;
File是我的EF datacontext的一个已知类:
public ObjectSet<File> Files
{
get { return _files ?? (_files = CreateObjectSet<File>("Files")); }
}
private ObjectSet<File> _files;
9条答案
按热度按时间ttisahbt1#
有没有一种方法来检索一个列表,但没有填写此列?
你不想被人看见。如果列已Map,则它是实体的自然组成部分。没有此列的实体不完整-它是不同的数据集=投影。
我在这里使用匿名类型,因为否则你会得到一个NotSupportedException:无法在LINQ to Entities查询中构造实体或复杂类型“ProjectName.File”。
作为例外,您不能投影到Map实体。我提到了上面的原因-投影使不同的数据集和EF不喜欢“部分实体”。
错误16错误3023:Map从第2717行开始的片段时出错:列文件。必须Map表文件中的数据:它没有默认值,并且不可为空。
仅从设计器中删除属性是不够的。你必须打开EDMX作为XML和删除列从SSDL以及这将使你的模型非常脆弱(每次更新数据库将把你的列)。如果你不想Map列,你应该使用不带列的数据库视图,Map视图而不是表,但是你将不能插入数据。
作为所有问题的解决方法,请使用table splitting并使用1:1与主
File
实体的关系。cidc1ykv2#
我会这样做
其中
Thing
是EF知道如何实现的实体。生成的SQL语句不应在其结果集中包含该大列,因为查询中不需要它。EDIT:您在编辑时会得到错误 NotSupportedException:无法在LINQ to Entities查询. 中构造实体或复杂类型“ProjectName.File”,因为尚未将该类Map为实体。您不能在LINQ to Entities查询中包含EF不知道的对象,并期望它生成适当的SQL语句。
您可以Map另一个在其定义中排除
VarBinary(MAX)
列的类型,或者使用上面的代码。jdzmm42g3#
你可以这样做:
或者这个:
取决于您的EF版本
qvtsj1bj4#
对于EF Core 2,我实现了这样的解决方案:
基本思想是将这个查询转换为例如:
变成这样:
你可以在这里看到完整的源代码:https://github.com/aspnet/EntityFrameworkCore/issues/1387#issuecomment-495630292
p3rjfoxz5#
我有这个要求,因为我有一个
Document
实体,它有一个Content
字段,其中包含文件的内容,即大约100 MB大小,我有一个搜索函数,我想返回其余的列。我选择使用投影:
然后我的WebApi控制器将这个
results
对象传递给一个公共的分页函数,该函数应用.Skip
、.Take
和.ToList
。这意味着当查询被执行时,它不会访问
Content
列,因此不会触及100 MB的数据,并且查询的速度与您希望/期望的一样快。接下来,我将其转换回我的DTO类,在本例中,它与实体类几乎完全相同,因此这可能不是您需要实现的步骤,但它遵循我的典型WebApi编码模式,因此:
然后我返回DTO列表:
所以它使用了投影,这可能不符合原始海报的要求,但如果您使用的是DTO类,那么无论如何都要进行转换。您可以轻松地执行以下操作,将它们作为实际实体返回:
只是多了几个步骤,但这对我来说很好。
更新:目前我使用的是扩展方法,所以我不必在访问这个实体的多个地方维护字段列表。所以我有:
然后我这样使用它:
请注意,这并不使用DTO,但它确实意味着您不能包含其他实体...
hivapdat6#
我想分享我的尝试,以解决这个问题的情况下,别人是在同样的情况。
我从Jeremy Danyow的建议开始,这对我来说是一个不那么痛苦的选择。
在我的例子中,我需要一个
IQueryable<>
结果对象,所以我在最后添加了AsQueryable()
。这当然让我添加了对.Where
、.Take
和其他我们都知道的命令的调用,它们工作得很好。但有一个警告:正常代码(基本上是
context.myEntity.AsQueryable()
)返回System.Data.Entity.DbSet<Data.DataModel.myEntity>
,而这种方法返回System.Linq.EnumerableQuery<Data.DataModel.myEntity>
。显然,这意味着我的自定义查询会在需要时“按原样”执行,而我后来添加的过滤是在之后完成的,而不是在数据库中。
因此,我试图通过使用EF创建的确切查询来模仿EntityFramework的对象,即使使用了
[Extent1]
别名,但它没有成功。在分析结果对象时,其查询的结束方式为FROM [dbo].[TableName] AS [Extent1].Where(c => ...
而不是预期的
FROM [dbo].[TableName] AS [Extent1] WHERE ([Extent1]...
不管怎样,这是可行的,只要表不是很大,这种方法就会足够快。否则,您别无选择,只能通过连接字符串手动添加条件,就像经典的动态SQL一样。如果你不知道我在说什么,我举个简单的例子:
如果你的方法有时需要这个字段,你可以添加一个
bool
参数,然后这样做:如果有人设法使Linq扩展像原来的EF对象一样正常工作,请评论,以便我可以更新答案。
hc8w905p7#
我在这里使用匿名类型,因为否则你会得到一个NotSupportedException:无法在LINQ to Entities查询中构造实体或复杂类型“ProjectName.File”。
另外,将表反规范化为进一步的表也不是一个坏的做法,即一个具有元数据,一个具有有效负载以避免投影。投影将工作,唯一的问题是,需要编辑任何时候一个新的列被添加到表。
jyztefdp8#
我试过这个:
在edmx图(EF 6)中,我单击了我想在EF中隐藏的列,并在它们的属性上将getter和setter设置为private。这样,对我来说,它工作。
我返回了一些包含User引用的数据,所以我想隐藏Password字段,即使它是加密和加盐的,我只是不想在我的json上,我不想做:
因为创建和维护这些数据是一件痛苦的事情,尤其是对于有很多关系的大表。
这种方法的缺点是,如果重新生成模型,则需要再次修改它们的getter和setter。
o4tp2gmn9#
使用Entity Framework Power Tools,您可以在efpt.config.json中执行以下操作: