C# 4.0 是否可以将ODataQueryOptions与DTO';s
C# 4.0 是否可以将ODataQueryOptions与DTO';s,c#-4.0,odata,dto,C# 4.0,Odata,Dto,ContentType-->EF型号 ContentTypes-->DTO 在我的OData控制器中: public Task<IQueryable<ContentTypes>> Get(ODataQueryOptions<ContentTypes> options) { var result = options.ApplyTo(_repository.Query().Get() .Where(u =>
ContentType
-->EF型号
ContentTypes
-->DTO
在我的OData控制器中:
public Task<IQueryable<ContentTypes>> Get(ODataQueryOptions<ContentTypes> options)
{
var result = options.ApplyTo(_repository.Query().Get()
.Where(u => u.UserId == userId)
.OrderBy(o => o.Description))
.Cast<ContentTypes>();
return result;
}
公共任务获取(ODataQueryOptions选项)
{
var result=options.ApplyTo(_repository.Query().Get())
.Where(u=>u.UserId==UserId)
.OrderBy(o=>o.Description))
.Cast();
返回结果;
}
尝试应用
ODataQueryOptions
时,我收到一个错误500。既然类已经继承了ODataController
,我甚至需要执行选项。ApplyTo(…)
?根据@ElHaix的答案更新。我强烈建议不要使用AutoMapper从这样的数据源进行映射。这还假设应用于存储库的查询是在调用数据库之前应用的
[Queryable]
public virtual IHttpResult Get()
{
var userId = 102; // mock
try
{
var results = _uow.Repository<ContentType>()
.Query()
.Get()
.Where(u => u.UserId == userId)
.OrderBy(o => o.Description)
.Select(x => new ContentTypeDTO()
{
//projection goes here
});
return this.Ok(results);
}
catch (Exception ex)
{
throw ex;
}
}
[可查询]
公共虚拟IHttpResult Get()
{
var userId=102;//mock
尝试
{
var results=\u uow.Repository()
.Query()
.Get()
.Where(u=>u.UserId==UserId)
.OrderBy(o=>o.Description)
.Select(x=>newcontenttypedto()
{
//投影在这里
});
返回这个。Ok(结果);
}
捕获(例外情况除外)
{
掷骰子;
}
}
另外,我会尝试对ElHaix的答案执行$select。解决方案是确保返回类型是DTO的类型,并且
ODataQueryOptions
应用于EF实体。然后我使用Automapper将结果映射到DTO
我已经根据@Schandlich的建议更新了答案,但是仍然存在一些问题:
[Queryable]
public virtual IHttpActionResult Get(ODataQueryOptions<ContentType> options)
{
var userId = 102; // mock
try
{
var results = options.ApplyTo(_uow.Repository<ContentType>()
.Query()
.Get()
.Include(u => u.User)
.Where(u => u.UserId == userId)
.OrderBy(o => o.Description)).Cast<ContentType>()
.Select(x => new ContentTypeDTO()
{
//projection goes here
ContentTypeId = x.ContentTypeId,
Description = x.Description,
UserDTO = new UserDTO
{
UserId = x.UserId,
UserName = x.User.UserName
}
});
return this.Ok(results);
}
catch (Exception ex)
{
throw ex;
}
}
[可查询]
公共虚拟IHttpActionResult获取(ODataQueryOptions选项)
{
var userId=102;//mock
尝试
{
var results=options.ApplyTo(_uow.Repository())
.Query()
.Get()
.包括(u=>u.User)
.Where(u=>u.UserId==UserId)
.OrderBy(o=>o.Description)).Cast()
.Select(x=>newcontenttypedto()
{
//投影在这里
ContentTypeId=x.ContentTypeId,
描述=x.描述,
UserDTO=新的UserDTO
{
UserId=x.UserId,
UserName=x.User.UserName
}
});
返回这个。Ok(结果);
}
捕获(例外情况除外)
{
掷骰子;
}
}
使用ODataQueryOptions
的原因是我希望EF在数据库调用级别处理向下过滤。否则,我将返回所有记录,然后Queryable
将返回,比如结果的第一页
我删除了Automapper代码,但很好奇为什么不使用它
然而,正如@Schandlich所指出的,这对
$select
或$expand
不起作用,我可以通过AutoMapper Project()扩展实现这一点$select、$filter等都应用于数据库查询
[TestMethod]
带有自动映射和OData选择测试()的公共无效数据形状
{
OracleMonitor myMonitor=新建OracleMonitor();
myMonitor.IsActive=true;
var dbcontext=new MyDbContext();
var datasource=dbcontext.Datasouces;
IsNotNull(数据源);
SetupAutoMapper();
var odataQuery=Extensions.CreateDummyODataQuery($expand=Fields($select=Description)和$select=Name);
var withShaping=datasource.Project().To();
Assert.IsNotNull(带形状);
var withODataQuery=odataQuery.ApplyTo(带形状);
Assert.IsNotNull(带ODataQuery);
字符串strJson=JsonConvert.SerializeObject(withODataQuery);
Assert.IsFalse(String.IsNullOrEmpty(strJson));
}
使用[Queryable]
属性并删除选项.ApplyTo()
,我从服务器获得31行。由于我想在服务器端应用过滤,使用options.ApplyTo()
,将执行请求10条记录的sql查询(而不是稍后在客户端进行过滤)。EF过滤器随后出现的原因是因为您处理投影的方式。看看我上面贴的答案。我还会查看您的存储库,确保其中没有ToList()或其他强制执行方法。另外,当您使用$select或$expand时,这将中断,因为结果将不是ContentType类型。@Schandlich-您的建议部分有效,并且当我排除选项时。ApplyTo()
,我不会返回所有其他OData信息,例如$inlinecount=allpages
的值,因此没有分页详细信息。我不想返回数据库中的所有记录,然后在客户端进行筛选。有数千条记录的情况又如何?执行$select
或$expand
失败是正确的。我怎样才能让它工作呢。另外,为什么不使用Automapper来做一些工作呢?这里有一篇关于为什么不使用Automapper的好文章。分页不起作用的原因是,在应用分页之前的某个时刻,查询已经命中数据库。我不知道是AutoMapper导致了这个问题,还是您的存储库导致了这个问题。我可能是演员的陈述。我会努力让它开箱即用,而不是试图强制展开和选择以使用您的设置。这就是我编写和使用的解决方案。我创建自己的接口而不是IRepository,而不是从控制器调用EF。实现该接口的数据源只执行一个干净的项目