OData或Code First失败:派生的导航属性
本文关键字:派生 导航 属性 失败 Code First OData | 更新日期: 2023-09-27 18:23:40
我遇到了一个复杂的情况,要么我的项目的代码优先部分有问题,要么我项目的OData部分有问题。。。
我有一个抽象类Person
,从中导出两个类User
和Driver
:
[DataContract]
[KnownType(typeof(User))]
[KnownType(typeof(Driver))]
public abstract class Person
{
[Key, DataMember]
public int ID { get; set; }
[DataMember]
public int RelationID { get; set; }
}
public class User : Person { }
public class Driver : Person { } // shortened for sake of readability
现在我有了一个模型Relation
,它可以包含用户和/或驱动程序。
[DataContract]
public class Relation
{
[Key, DataMember]
public int ID { get; set; }
[DataMember]
public virtual ICollection<User> Users { get; set; }
[DataMember]
public virtual ICollection<Driver> Drivers { get; set; }
}
问题是,当我让Code First生成迁移代码时,我可以看到它想要添加两列Relation_ID
和Relation_ID1
,以处理Users
和Drivers
的映射。我将[InverseProperty("ID")]
属性应用于两个导航属性,以便尝试解决此问题(如本文所述:Code First DataAnnotations)。但问题依然存在。所以,这是行不通的。
现在,您会说:为什么不将其设为ICollection<Person> People
属性,并使用this.db.People.OfType<User>()
将对象强制转换到正确的模型并以这种方式检索它呢。这是完全可以接受的,但现在它变成了OData问题。
我希望能够从Relations
控制器调用public IQueryable<User> GetUsers([FromODataUri] int key)
,以便使用/odata/Relations(16)/Users
从关系中获取所有用户。如果Relation
模型中不存在Users
属性,OData解析器将拒绝任何此类调用,因为它无法解析为正确的方法。
所以我被夹在两个世界的设计之间。我猜,为了正确地解决这个问题,重点应该放在代码第一部分,而不是OData部分。任何想法都很感激,提前谢谢!
您还可以添加ICollection People属性,并从数据模型中排除Users和Drivers属性。例如,
[DataContract]
public class Relation
{
[Key, DataMember]
public int ID { get; set; }
[DataMember]
public virtual ICollection<Person> People { get; set; }
[DataMember]
public virtual ICollection<User> Users
{
get
{
return People.OfType<User>();
}
}
[DataMember]
public virtual ICollection<Driver> Drivers
{
get
{
return People.OfType<Driver>();
}
}
}
在您的DbModelBuilder代码中,通过执行排除用户和驱动程序属性
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var relation = modelBuilder.Entity<Relation>();
relation.Ignore(p => p.Users);
relation.Ignore(p => p.Drivers);
}
在ODataModelBuilder中,如果需要,请排除People属性。