C# 从entityframework检索不带字段的对象

C# 从entityframework检索不带字段的对象,c#,.net,sql,entity-framework,C#,.net,Sql,Entity Framework,我正在使用实体框架连接数据库。我有一个小问题: 我有一个表,其中有一个varbinary(MAX)列(带有filestream) 我使用SQL请求来管理“数据”部分,但其余部分(文件的元数据)使用EF 我有一个代码,它必须获得所有文件的id,文件名,guid,修改日期。。。一个文件的名称。这根本不需要“数据”字段 有没有一种方法可以在不填充此列的情况下检索列表 差不多 context.Files.Where(f=>f.xyz).Exclude(f=>f.Data).ToList();

我正在使用实体框架连接数据库。我有一个小问题:

我有一个表,其中有一个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”。)

(例如,此代码引发以前的异常:

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;
文件是my EF datacontext的已知类:

public ObjectSet<File> Files
{
    get { return _files  ?? (_files = CreateObjectSet<File>("Files")); }
}
private ObjectSet<File> _files;
公共对象集文件
{
获取{return\u files??(\u files=CreateObjectSet(“files”);}
}
私有对象集文件;

我会这样做:

var result = from thing in dbContext.Things
             select new Thing {
                 PropertyA = thing.PropertyA,
                 Another = thing.Another
                 // and so on, skipping the VarBinary(MAX) property
             };
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();
var files = context.Files.AsNoTracking()
                         .IgnoreProperty(f => f.Report)
                         .ToList();
其中
Thing
是EF知道如何具体化的实体。生成的SQL语句不应在其结果集中包含大列,因为查询中不需要它

编辑:从您的编辑中,您会得到错误NotSupportedException:无法在LINQ到Entities查询中构造实体或复杂类型“ProjectName.File”。因为您尚未将该类映射为实体。您不能在LINQ到Entities查询中包含EF不知道的对象,并期望它能够生成适当的SQL语句

您可以映射其定义中不包含
VarBinary(MAX)
列的另一个类型,也可以使用上面的代码

有没有一种方法可以在不填充此列的情况下检索列表

如果列被映射,则它是实体的自然部分。没有此列的实体不完整-它是不同的数据集=投影

我在这里使用匿名类型,因为否则您将获得 NotSupportedException:实体或复杂类型“ProjectName.File” 无法在LINQ到实体查询中构造

作为例外,您不能投影到映射的实体。我提到了上面的原因-投影生成不同的数据集,EF不喜欢“部分实体”

错误16错误3023:映射从第行开始的片段时出现问题 2717:列文件。必须映射表文件中的数据:它没有 默认值,不可为空

仅从设计器中删除属性是不够的。您必须以XML形式打开EDMX并从SSDL中删除列,这将使您的模型非常脆弱(数据库中的每次更新都会将列放回原处)。如果不想映射列,则应使用不带列的数据库视图,并映射视图而不是表,但您将无法插入数据

作为解决所有问题的方法,请使用有问题的二进制列,并将其与主
文件
实体以1:1的关系分隔到另一个实体。

您可以执行以下操作:

var files = dbContext.Database.SqlQuery<File>("select FileId, DataType, MimeType from Files");
var files=dbContext.Database.SqlQuery(“从文件中选择FileId、DataType、MimeType”);
或者这个:

var files = objectContext.ExecuteStoreQuery<File>("select FileId, DataType, MimeType from Files");
var files=objectContext.ExecuteStoreQuery(“从文件中选择文件ID、数据类型、MimeType”);

根据您的EF版本,我想与大家分享一下我解决这个问题的方法,以防其他人遇到同样的情况

我从建议开始,这对我来说是一个不那么痛苦的选择

// 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");
如果您的方法有时需要此字段,您可以添加
bool
参数,然后执行以下操作:

var result = from thing in dbContext.Things
             select new Thing {
                 PropertyA = thing.PropertyA,
                 Another = thing.Another
                 // and so on, skipping the VarBinary(MAX) property
             };
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();
var files = context.Files.AsNoTracking()
                         .IgnoreProperty(f => f.Report)
                         .ToList();
IQueryable结果;
if(不包括BigData)
results=context.Database.SqlQuery(“从TableName中选择Field1、Field2、Field3、HugeField4=NULL、Field5”).AsQueryable();
其他的
结果=context.myEntity.AsQueryable();

如果有人设法使Linq扩展正常工作,就像它是原始EF对象一样,请发表评论,以便我可以更新答案。

我有这个要求,因为我有一个
文档
实体,它有一个
内容
字段,其中包含文件的内容,即大约100MB大小,我有一个搜索功能,可以希望返回其余的列

我选择使用投影:

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
});
然后返回DTO列表:

return Ok(dtos);
因此,它使用投影,这可能不符合原始海报的要求,但如果您使用DTO类,您仍然在转换。您可以轻松地执行以下操作,将它们作为实际实体返回:

var dtos = paginated.Select(o => new Document
{
    Content = o.Content,
    ContentType = o.ContentType,
    DocumentTypeId = o.DocumentTypeId,
    //...
只需多做几步,但这对我来说效果很好。

我尝试了以下方法:

在edmx图(EF 6)中,我单击了我想对EF隐藏的列,在它们的属性上,您可以将它们的getter和setter设置为private

我返回了一些包含用户引用的数据,因此我想隐藏密码字段,即使它是加密和盐渍的,我只是不希望它出现在我的json上,我也不想执行以下操作:

Select(col => new {}) 
因为这是一个痛苦的创建和维护,特别是对于有很多关系的大表

这种方法的缺点是,如果重新生成模型,则需要再次修改它们的getter和setter

我在这里使用匿名类型,因为否则您将获得 NotSupportedException:实体或复杂类型“ProjectName.File” 无法在LINQ到实体查询中构造

而且将表反规范化为
SELECT [f].[Id], [f].[Report], [f].[CreationDate]
FROM [File] AS [f]
SELECT [f].[Id], '' as [Report], [f].[CreationDate]
FROM [File] AS [f]