从一个没有ONE字段的entityframework中检索一个对象
我正在使用entity framework来连接数据库。 我有一个小问题:
我有一个表有一个varbinary(MAX)列(文件stream)。
我使用SQL请求来pipe理“数据”部分,但其余的EF(文件的元数据)。
我有一个代码,必须获得文件的所有文件ID,文件名,GUID,修改date…。 这根本不需要“数据”字段。
有没有办法检索一个列表,但没有填写这个列?
就像是
context.Files.Where(f=>f.xyz).Exclude(f=>f.Data).ToList();
??
我知道我可以创build匿名对象,但是我需要将结果传递给一个方法,所以没有匿名方法。 我不想把它放在一个匿名types列表中,然后创build一个非匿名types(File)的列表。
目标是避免这种情况:
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 }; }
(我在这里使用的匿名types,否则你会得到一个NotSupportedException:实体或复杂types'ProjectName.File'不能在LINQ to Entities查询中构造。
(例如,这个代码抛出了以前的exception:
File file2 = context.Files.Where(f => f.Id == idFile) .Select(f => new File() {Id = f.Id, DataType = f.DataType}).FirstOrDefault();
和“文件”是我得到一个context.Files.ToList()
的types。 这是一个好class级:
using File = MyProjectNamespace.Common.Data.DataModel.File;
文件是我的EF datacontext的一个已知的类:
public ObjectSet<File> Files { get { return _files ?? (_files = CreateObjectSet<File>("Files")); } } private ObjectSet<File> _files;
有没有办法检索一个列表,但没有填写这个列?
不是没有你想避免的投影。 如果该列被映射,则它是您的实体的自然部分。 没有这个列的实体不完整 – 它是不同的数据集=投影。
我在这里使用的匿名types,否则你会得到一个NotSupportedException:实体或复杂types“ProjectName.File”不能在LINQ to Entities查询中构造。
作为例外说你不能投影到映射的实体。 我上面提到的原因 – 投影做了不同的数据集,EF不喜欢“部分实体”。
错误16错误3023:从行2717开始映射片段中的问题:表文件中的列Files.Data必须被映射:它没有默认值,并且不可为空。
从devise师身上删除财产是不够的。 您必须打开EDMX作为XML并从SSDL删除列,这将使您的模型非常脆弱(从数据库的每个更新将把您的列回)。 如果您不想映射列,则应使用不带列的数据库视图,并映射视图而不是表格,但不能插入数据。
作为解决所有问题的一种解决方法,使用表格拆分并将有问题的二进制列与1:1关系分隔到另一个实体,以便与您的主File
实体关联。
我会做这样的事情:
var result = from thing in dbContext.Things select new Thing { PropertyA = thing.PropertyA, Another = thing.Another // and so on, skipping the VarBinary(MAX) property };
凡是EF知道如何实现的实体。 生成的SQL语句不应在其结果集中包含较大的列,因为查询中不需要该列。
编辑 :从您的编辑,你会得到错误NotSupportedException:实体或复杂types“ProjectName.File”不能在LINQ to Entities查询中构造。 因为您还没有将该类映射为实体。 您不能将LINQ中的对象包含到EF不知道的实体查询中,并期望它生成适当的SQL语句。
您可以映射排除其定义中的VarBinary(MAX)
列的其他types或使用上面的代码。
你可以这样做:
var files = dbContext.Database.SqlQuery<File>("select FileId, DataType, MimeType from Files");
或这个:
var files = objectContext.ExecuteStoreQuery<File>("select FileId, DataType, MimeType from Files");
取决于您的EF版本
我有这样的要求,因为我有一个Document
实体有一个Content
字段与文件的内容,即100MB大小,我有一个searchfunction,我想返回其余的列。
我select使用投影:
IQueryable<Document> results = dbContext.Documents.Include(o => o.UploadedBy).Select(o => new { Content = (string)null, ContentType = o.ContentType, DocumentTypeId = o.DocumentTypeId, FileName = o.FileName, Id = o.Id, // etc. even with related entities here like: UploadedBy = o.UploadedBy });
然后我的WebApi控制器将这个results
对象传递给一个通用的分页函数,该函数应用了.Skip
, .ToList
和.ToList
。
这意味着当查询被执行时,它不访问Content
列,所以100MB的数据没有被触及,查询速度就像你期望的那样快。
接下来,我把它放回到我的DTO类中,在这种情况下,它与实体类几乎完全相同,所以这可能不是您需要实现的步骤,但它遵循我典型的WebApi编码模式,因此:
var dtos = paginated.Select(o => new DocumentDTO { Content = o.Content, ContentType = o.ContentType, DocumentTypeId = o.DocumentTypeId, FileName = o.FileName, Id = o.Id, UploadedBy = o.UploadedBy == null ? null : ModelFactory.Create(o.UploadedBy) });
然后我返回DTO列表:
return Ok(dtos);
所以它使用的投影,可能不符合原来的海报的要求,但如果你正在使用DTO类,无论如何你正在转换。 你可以简单地做到以下几点,将它们作为实际的实体返回:
var dtos = paginated.Select(o => new Document { Content = o.Content, ContentType = o.ContentType, DocumentTypeId = o.DocumentTypeId, //...
只是几个额外的步骤,但这对我来说很好。
我想分享我的努力,以解决这个问题,以防其他人处于相同的情况。
我从丹尼尔 ( Jeremy Danyow)的build议开始,对我来说这是不那么痛苦的select。
// You need to include all fields in the query, just make null the ones you don't want. var results = context.Database.SqlQuery<myEntity>("SELECT Field1, Field2, Field3, HugeField4 = NULL, Field5 FROM TableName");
在我的情况下,我需要一个IQueryable<>
结果对象,所以我最后添加了AsQueryable()
。 这当然让我加上电话,其中,我们都知道,其他的命令,他们工作得很好。 但有一个警告:
正常的代码(基本上context.myEntity.AsQueryable()
)返回一个System.Data.Entity.DbSet<Data.DataModel.myEntity>
,而这种方法返回System.Linq.EnumerableQuery<Data.DataModel.myEntity>
。
显然,这意味着我的自定义查询按照“按原样”立即执行,稍后添加的过滤将在后面完成,而不是在数据库中完成。
因此,我试图通过使用EF创build的确切查询来模仿entity framework的对象,即使是那些[Extent1]
别名,但它不起作用。 分析结果对象时,其查询结束
FROM [dbo].[TableName] AS [Extent1].Where(c => ...
而不是预期的
FROM [dbo].[TableName] AS [Extent1] WHERE ([Extent1]...
无论如何,这个工作,只要桌子不是很大,这个方法就够快了。 否则,您没有办法通过连接string手动添加条件,如传统的dynamicSQL。 一个非常基本的例子,如果你不知道我在说什么:
string query = "SELECT Field1, Field2, Field3, HugeField4 = NULL, Field5 FROM TableName"; if (parameterId.HasValue) query += " WHERE Field1 = " + parameterId.Value.ToString(); var results = context.Database.SqlQuery<myEntity>(query);
如果你的方法有时需要这个字段,你可以添加一个bool
参数,然后做这样的事情:
IQueryable<myEntity> results; if (excludeBigData) results = context.Database.SqlQuery<myEntity>("SELECT Field1, Field2, Field3, HugeField4 = NULL, Field5 FROM TableName").AsQueryable(); else results = context.myEntity.AsQueryable();
如果任何人设法使Linq扩展正常工作,就像它是最初的EF对象一样,请注释,以便我可以更新答案。
我试过这个:
从edmx图(EF 6)中,我点击了我想要从EF隐藏的列和他们的属性,你可以将他们的getter和setter设置为private。 这样,对我来说,它的工作。
我返回一些包含用户引用的数据,所以我想隐藏密码字段,即使它被encryption和腌制,我只是不希望它在我的JSON,我不想做一个:
Select(col => new {})
因为这是一个很难创build和维护,特别是对于有很多关系的大桌子。
这种方法的缺点是,如果你重新生成你的模型,你将需要再次修改他们的getter和setter。
- .NET:当所需的configuration设置丢失时抛出哪个exception?
- Visual Studio跳转到下一个错误快捷方式?
- Application.OpenForms.Count = 0总是
- 我如何提高ASP.NET MVC应用程序的性能?
- 使用reflection设置对象属性
- 不能将types'System.Collections.Generic.IEnumerable <AnonymousType#1>'隐式转换为'System.Collections.Generic.List <string>
- 缺lessentity framework包含(lambda)扩展
- entity framework代码首先AddOrUpdate方法插入重复值
- 哪个更快:清除收集或实例化新的