【发布时间】:2021-06-01 06:31:13
【问题描述】:
我有两个 OData 控制器:
PersonsController
PersonsUnrestrictedController
它们不同的唯一方式是几个属性必须根据控制器从persons表中的不同列获取它们的值。
PersonsController 将发回 Person 列表,其中 Person 的名字、姓氏等是别名,而 PersonsUnrestrictedController 将发回带有这些人的真实姓名的 Person 列表。所有其他属性将完全相同,包括导航属性及其与其他表的关系。
PersonsController 在任何情况下都不能透露一个人的真实姓名,这一点非常重要。
是否可以动态切换:
[Column("AltGivenName")]
public string GivenName { get; set; }
和
[Column("GivenName")]
public string GivenName { get; set; }
取决于控制器?
或者有两个属性 GivenName 和 AltGivenName 并根据控制器动态隐藏/显示其中 1 个:
[DataMember(Name="GivenName")] //Either should this one be ignored
public string AltGivenName { get; set; }
public string GivenName { get; set; } //or this one, depending on controller
或者还有其他可能的解决方法吗?
编辑:添加我的代码
Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PersonContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("MyConnection")); });
services.AddOData();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapODataRoute("odata", "odata", GetEdmModel());
endpoints.Select().Expand().MaxTop(null).Count();
});
}
private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
var persons = builder.EntitySet<Person>("Persons");
return builder.GetEdmModel();
}
}
PersonContext.cs
public class PersonContext : DbContext
{
public DbSet<DbPerson> Persons { get; set; }
public PersonContext(DbContextOptions<PersonContext> options) : base(options)
{
}
}
DbPerson.cs
[Table("Person")]
public class DbPerson
{
[Key]
public int Id { get; set; }
public string GivenName { get; set; }
public string AltGivenName { get; set; }
}
Person.cs
public class Person
{
[Key]
public int Id { get; set; }
public string GivenName { get; set; }
}
MappingHelper.cs
public static class MappingHelper
{
public static Person ToPerson(this DbPerson dbPerson)
{
return new Person
{
Id = dbPerson.Id,
GivenName = dbPerson.GivenName,
};
}
public static Person ToAnonymousPerson(this DbPerson dbPerson)
{
return new Person
{
Id = dbPerson.Id,
GivenName = dbPerson.AltGivenName,
};
}
}
PersonsController.cs
public class PersonsController : ODataController
{
private readonly PersonContext _context;
public PersonsController(PersonContext context)
{
_context = context;
}
[EnableQuery]
public IActionResult Get()
{
return new ObjectResult(_context.Persons.Select(MappingHelper.ToPerson));
}
}
运行以下查询需要 5-10 秒 http://localhost:4871/odata/persons?$top=10
如果我改变:
return new ObjectResult(_context.Persons.Select(MappingHelper.ToPerson));
到
return new ObjectResult(_context.Persons);
改变
var persons = builder.EntitySet<Person>("Persons");
到
var persons = builder.EntitySet<DbPerson>("Persons");
相同的查询需要 50-100 毫秒
person 表中有大约 150k 人。
【问题讨论】:
-
请显示两个控制器之间的一些示例 url,例如,您是否希望使用两条不同的路由,或者是否有其他机制来确定这是受限制还是不受限制的查询?您的示例只有“/Persons”路线。
-
您还可以展示您希望每个控制器提供的一两个其他功能或操作,以帮助展示您的需求的动态性质。
-
您希望在
PersonsController上支持哪些操作?为什么它需要是一个完全独立的控制器?
标签: c# asp.net-core asp.net-web-api odata