1

I'm having a complex situation where I either get a problem with the Code-First portion of my project, or a problem with the OData portion of my project...

I have an abstract class Person of which I derive two classes User and 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

Now I have a model Relation, which can contain both users and/or drivers.

[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; }
}

The problem is, when I let Code-First generate migration code, I can see that it wants to add two columns Relation_ID and Relation_ID1 in order to cope with the mapping of Users and Drivers. I applied the [InverseProperty("ID")] attribute to both navigation properties in order to try to solve this (as described here: Code First DataAnnotations). But still, the problem persists. So, this is not working.

Now, you would say: why not make it an ICollection<Person> People property, and use this.db.People.OfType<User>() in order to cast the objects to the right model and retrieve it that way. This is perfectly acceptable, but now it turns into an OData problem.

I want to be able to call public IQueryable<User> GetUsers([FromODataUri] int key) from the Relations controller in order to use /odata/Relations(16)/Users to get all users from a relation. If there is no Users property present in the Relation model, the OData parser rejects any such call because it can not resolve to the correct method.

So I'm stuck between the designs of both worlds. I'm guessing that in order to correctly solve this problem, the focus should lie on the Code-First part, not on the OData part. Any ideas are appreciated, thanks in advance!

4

1 に答える 1

1

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 コードで、次のようにして、Users プロパティと Drivers プロパティを除外します。

    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 に答える