【发布时间】:2017-11-12 13:32:43
【问题描述】:
我在 C# Web API OData 中使用以下代码并尝试对 LanguageId 进行过滤,但在应用过滤器时出现以下错误
模型
namespace ODataSample
{
public class Project
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public long CreatedBy { get; set; }
public long UpdatedBy { get; set; }
public decimal Cost { get; set; }
public long StatusId { get; set; }
[ForeignKey("StatusId")]
public virtual ProjectStatus Status { get; set; }
}
public class ProjectStatus
{
public ProjectStatus()
{
ProjectStatusTexts = new HashSet<ProjectStatusText>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long StatusId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<ProjectStatusText> ProjectStatusTexts { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public class ProjectStatusText
{
public ProjectStatusText()
{
ProjectStatus = new HashSet<ProjectStatus>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public long StatusId { get; set; }
[ForeignKey("StatusId")]
public IEnumerable<ProjectStatus> ProjectStatus { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public long LanguageId { get; set; }
[ForeignKey("LanguageId")]
public virtual Language Language { get; set; }
public bool IsActive { get; set; }
}
public class Language
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long LanguageId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
}
public class User
{
public User()
{
this.Projects = new HashSet<Project>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long UserId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
}
上述模型的服务
namespace ODataSample.Services
{
public class ProjectsService
{
public IQueryable<Project> GetProjects()
{
var ctx = new ProjectsContext();
return ctx.Projects;
}
}
}
带有种子数据的DbContext 和DbInitializer
namespace ODataSample.Contexts
{
public class ProjectsContext : DbContext
{
public ProjectsContext() : base("ProjectsConnectionString") { Database.SetInitializer(new ProjectDBInitializer()); }
public ProjectsContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
Database.SetInitializer(new ProjectDBInitializer());
}
public DbSet<Project> Projects { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<ProjectStatus> ProjectStatuses { get; set; }
public DbSet<ProjectStatusText> ProjectStatusTexts { get; set; }
public DbSet<Language> Languages { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
public class ProjectDBInitializer : DropCreateDatabaseAlways<ProjectsContext>
{
public ProjectDBInitializer()
{
}
protected override void Seed(ProjectsContext context)
{
context.Languages.AddRange(new[]
{
new Language { Description = "Spanish", IsActive = true, LanguageId = 1, Name = "es" },
new Language { Description = "English", IsActive = true, LanguageId = 2, Name = "en" }
});
context.ProjectStatuses.AddRange(new[]
{
new ProjectStatus { StatusId=1, Name="Active", Description="Active", IsActive= true },
new ProjectStatus { StatusId=2, Name="Closed", Description="Closed", IsActive= true },
new ProjectStatus { StatusId=3, Name="InProgress", Description="In Progress", IsActive= true }
});
context.ProjectStatusTexts.AddRange(new[]
{
new ProjectStatusText {Id = 1, LanguageId=1, StatusId = 1,Name = Path.GetRandomFileName(),Description = Path.GetRandomFileName(),IsActive=true },
new ProjectStatusText {Id = 2, LanguageId=2, StatusId = 1,Name = "Active",Description = "Active",IsActive=true },
new ProjectStatusText {Id = 3, LanguageId=1, StatusId = 2,Name = Path.GetRandomFileName(),Description = Path.GetRandomFileName(),IsActive=true },
new ProjectStatusText {Id = 4, LanguageId=2, StatusId = 3,Name = "InProgress",Description = "InProgress",IsActive=true }
});
context.Projects.AddRange(new[]
{
new Project{ Cost = default(decimal), Id=1,Name="project 1",StatusId = 1, Description="project 1", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, CreatedBy = 1, UpdatedBy =1},
new Project{ Cost = default(decimal), Id=2,Name="project 2",StatusId = 1, Description="project 2", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, CreatedBy = 1, UpdatedBy =1},
new Project{ Cost = default(decimal), Id=3,Name="project 3",StatusId = 1, Description="project 3", CreatedOn = DateTime.Now, UpdatedOn = DateTime.Now, CreatedBy = 1, UpdatedBy =1 }
});
base.Seed(context);
}
}
}
以下是WebApiConfig的注册情况
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Project>("Projects");
modelBuilder.EntitySet<ProjectStatus>("ProjectStatusses");
modelBuilder.EntitySet<ProjectStatusText>("ProjectStatusTexts");
modelBuilder.EntitySet<Language>("Languages");
modelBuilder.EntitySet<User>("Users");
var edmModel = modelBuilder.GetEdmModel();
config.Routes.MapODataRoute("odata", "odata", edmModel);
问题:
我有Project 实体,其状态可用,如新、活动、进行中等。当我尝试对这些值进行本地化时,我发现拥有文本类/表的方法会很容易。因此创建了ProjectStatusTexts 类/表。
当我尝试使用翻译后的值获取项目时,我正在使用浏览器中的以下 OData 查询,但它不会过滤记录,因为 EF 为 any生成的 where 条件> URI 中的子句返回ProjectStatusTexts 表中的所有记录。
我也尝试过 StackOverflow 中给出的以下方法,但无法修复。这个模型有什么问题 C# 看不懂还是 OData Query URI 有问题,请帮忙。
查询 URI: http://localhost:64046/odata/Projects?$expand=Status/ProjectStatusTexts&$filter=Status/ProjectStatusTexts/any(l:l/Language/LanguageId%20eq%202)
var projects = (EdmEntitySet)edmModel.EntityContainers().Single().FindEntitySet("Projects");
var projectStatusTexts = (EdmEntitySet)edmModel.EntityContainers().Single().FindEntitySet("ProjectStatusTexts");
var projectType = (EdmEntityType)edmModel.FindDeclaredType("ODataSample.Project");
var projectStatusTextsType = (EdmEntityType)edmModel.FindDeclaredType("ODataSample.ProjectStatusText");
var partsProperty = new EdmNavigationPropertyInfo();
partsProperty.TargetMultiplicity = EdmMultiplicity.Many;
partsProperty.Target = projectStatusTextsType;
partsProperty.ContainsTarget = false;
partsProperty.OnDelete = EdmOnDeleteAction.Cascade;
partsProperty.Name = "ProjectStatusTexts";
//projects.AddNavigationTarget(projectType.AddUnidirectionalNavigation(partsProperty), projectStatusTexts);
var navigationProperty = projectType.AddUnidirectionalNavigation(partsProperty);
projects.AddNavigationTarget(navigationProperty, projectStatusTexts);
var linkBuilder = edmModel.GetEntitySetLinkBuilder(projects);
linkBuilder.AddNavigationPropertyLinkBuilder(navigationProperty,
new NavigationLinkBuilder((context, property) =>
context.GenerateNavigationPropertyLink(property, false), true));
config.Routes.MapODataRoute("odata", "odata", edmModel);
【问题讨论】:
-
我对你的数据模型有点不清楚,是否可以提供更多关于这些东西代表什么以及你试图过滤什么的细节?
-
我正在尝试按给定语言过滤项目状态。该项目有一个从 ProjectStatus 获取的 statusid,它是本地化的,并且本地化数据可从 ProjectStatusTexts 表中获得每种语言。当我得到一个项目时,我想按用户的语言显示 StatusText。例如:西班牙语
标签: c# entity-framework odata