1

我遇到了一个复杂的情况,要么我的项目的 Code-First 部分出现问题,要么我的项目的 OData 部分出现问题......

我有一个抽象类Person,我派生出两个类UserDriver

[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_IDRelation_ID1以应对 和 的Users映射Drivers。我将该[InverseProperty("ID")]属性应用于两个导航属性以尝试解决此问题(如此处所述:Code First DataAnnotations)。但是,问题仍然存在。所以,这是行不通的。

现在,你会说:为什么不让它成为一个ICollection<Person> People属性,并使用它this.db.People.OfType<User>()来将对象转换为正确的模型并以这种方式检索它。这是完全可以接受的,但现在它变成了 OData 问题。

我希望能够public IQueryable<User> GetUsers([FromODataUri] int key)Relations控制器调用,以便/odata/Relations(16)/Users从关系中获取所有用户。如果模型中不Users存在任何属性Relation,OData 解析器将拒绝任何此类调用,因为它无法解析为正确的方法。

所以我被困在两个世界的设计之间。我猜为了正确解决这个问题,重点应该放在 Code-First 部分,而不是 OData 部分。任何想法表示赞赏,在此先感谢!

4

1 回答 1

1

您也可以添加 ICollection People 属性,并从数据模型中排除用户和驱动程序属性。例如,

[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 属性。

于 2013-07-18T20:46:38.520 回答