ASP.NET C# OData 服务 + 导航属性 + $expand = null。我错过了啥?

Posted

技术标签:

【中文标题】ASP.NET C# OData 服务 + 导航属性 + $expand = null。我错过了啥?【英文标题】:ASP.NET C# OData Service + Navigation Property + $expand = null. What am I missing?ASP.NET C# OData 服务 + 导航属性 + $expand = null。我错过了什么? 【发布时间】:2021-05-28 22:13:10 【问题描述】:

我将尝试通过一个简化的示例尽可能彻底地解释我的问题。请注意,我没有使用实体框架。

我有这个模型:

public class Person

    [Key]
    public Guid Id  get; set; 
    public string GivenName  get; set; 
    public string FamilyName  get; set; 
    public List<Employment> Employments  get; set;  


public class Employment

    public string Role  get; set; 
    public Guid? ManagerId  get; set; 
    public virtual Person Manager  get; set; 

我创建了一个内存数据源:

public class MyDataSource

    private static MyDataSource instance = null;
    public static MyDataSource Instance
    
        get
        
            if (instance == null)
            
                instance = new MyDataSource();
            
            return instance;
        
    
    public List<Person> Persons   get; set; 
    private MyDataSource()
    
        this.Persons = new List<Person>();
        this.Persons.AddRange(new List<Person>
        
            new Person()
            
                Id = Guid.Parse("00000000-0000-0000-0000-000000000001"), //Just for simplicity
                GivenName = "John",
                FamilyName = "Doe",
                Employments = new List<Employment>()
                
                    new Employment()
                    
                        Role = "Boss"
                    
                
            ,
            new Person()
            
                Id = Guid.Parse("00000000-0000-0000-0000-000000000002"), //Just for simplicity
                GivenName = "Clark",
                FamilyName = "Kent",
                Employments = new List<Employment>()
                
                    new Employment()
                    
                        Role = "Worker",
                        ManagerId = Guid.Parse("00000000-0000-0000-0000-000000000001"), //Just for simplicity
                    
                
            
        );
    

我有这个控制器:

[EnableQuery]
public class PersonsController : ODataController

    public IHttpActionResult Get()
    
        return Ok(MyDataSource.Instance.Persons)
    

我配置了 EndPoint:

public static class WebApiConfig

    public static void Register(HttpConfiguration config)
    
        config.MapODataServiceRoute("ODataRoute", "odata", CreateEdmModel());
        config.Select().Expand().Filter().OrderBy().MaxTop(null).Count()
    

    public static IEdmModel CreateEdmModel()
    
        var builder = new ODataConventionModelBuilder();
        var persons = builder.EntitySet<Person>("Persons");
        builder.ComplexType<Employment>().HasOptional(e => e.Manager, (e, p) => e.ManagerId == p.Id);
        return builder.GetEdmModel();
    

检查 $metadata 我看到了这个:

<NavigationProperty Name="Manager" Type = "MyNamespace.Person">
    <ReferentialConstraint Property="ManagerId" ReferenceProperty="Id" />
</NavigationProperty

据我所知,一切看起来都很好,但是:

https://example.com/odata/persons?$expand=Employments/Manager

一切正常,但是:

Manager 对于两个人都是空的。我期待看到 John Doe 对 Clark Kents 的工作。

我错过了什么?

【问题讨论】:

【参考方案1】:

我自己解决了。

我意识到它不像我想象的那样工作,我必须直接在 MyDataSource 中添加对管理器的引用。之后,它可以 $expand 管理器。

【讨论】:

如果您使用像 EntityFramework 这样的 ORM 作为数据源,那么只要 DbContext 可以解析查询,您最初的期望就会奏效。您已经有效地定义了手动投影,IQueryable 只能查询您定义的内容,因此您是正确的,您必须确保定义并包含对 Manager 导航属性的引用。

以上是关于ASP.NET C# OData 服务 + 导航属性 + $expand = null。我错过了啥?的主要内容,如果未能解决你的问题,请参考以下文章

Asp.Net MVC4 Web API - 我们是不是需要 OData 来构建快速查询服务

ASP .NET MVC 4 WebApi:手动处理 OData 查询

如何从 C# 控制器(OData)的 JSON 序列化中修复丢失的子对象(导航属性)?

如何正确地将 OData 与 ASP.net Core 集成

ASP.NET MVC C# 如何分隔导航栏链接?

使用 ASP.NET Core OData 8.0 映射动态 OData 路由