OData服务不返回自定义对象

时间:2011-06-30 23:01:29

标签: entity-framework odata

这是我想要做的:

  1. 我有一个现有的数据库,我需要从中获取数据。

  2. 我创建了数据合同,通过使用Entity Framework将它们映射到各个表。在我的例子中,我有三个表 - tblOrder,tblProduct和tblCustomer。所以我创建了三个数据合同来映射到这些表。实体框架注释已添加到数据承诺中。我写了一个单元测试来测试我的数据合同。通过直接的Entity Framework调用,一切都按预期工作。见下面的单元测试1.

  3. 为每个数据协定添加了DataServiceKey批注。并通过添加订单上下文和数据服务svc将它们与OData服务包装在一起。见下文。

  4. 写了一个单元测试,通过OData服务访问一些现有的订单数据。问题:OData服务仅返回Order对象上的非自定义数据类型。它在客户数据类型字段(例如CustomerInfo和ProductList)上返回null。

  5. 我做错了吗?对于使用EF进行检索的OData调用来处理对象有什么特别之处吗?


    [DataServiceKey("ID")]      
    [Table("tblOrder", Schema = "schOnlineSale")]      
    public class Order     
    {     
    
         [Column("OrderId"), Key]        
         public int ID { get; set; }
    
         public string OrderName { get; set; }
    
         public int CustomerId { get; set; }
    
         [ForeignKey("CustomerId")]
         public virtual Customer CustomerInfo { get; set; }
    
         [ForeignKey("OrderId")]
         public virtual ICollection<Product> ProductList{ get; set; }
    }
    
    [DataServiceKey("CustomerId")]     
    [Table("tblCustomer", Schema = "schOnlineSale")]     
    public class Customer    
    {
    
         [Key]
         public int CustomerId{ get; set; }
    
         [Column("FullName")]
         public string Name { get; set; }
    
         public string MailingAddress { get; set; }   
         public string City { get; set; }   
         public string State { get; set; }   
         public string ZIPCode { get; set; }   
    }
    
    [DataServiceKey("ProductId")]   
    [Table("tblProduct", Schema = "schOnlineSale")]    
    public class Product    
    {
    
         [Key]
         public int ProductId{ get; set; }
    
         public int OrderId{ get; set; }
    
         public string ProductName { get; set; }
    
         public decimal SalePrice { get; set; }   
    }
    

    //OData Service wrapper classes    
    public class OrderContext:  DbContext    
    {        
    
         public DbSet<Order> Orders {get; set;}
    
         public DbSet<Product> Products {get; set;}
    }
    
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]   
    public class OrderDataService : DataService<OrderContext>    
    {
    
            // This method is called only once to initialize service-wide policies.
            public static void InitializeService(DataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule("Orders", EntitySetRights.All);
                config.SetEntitySetAccessRule("Products", EntitySetRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
                config.UseVerboseErrors = true;
            }
    
            protected override void HandleException(HandleExceptionArgs args)
            {
                try
                {
                    args.UseVerboseErrors = true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
    
            protected override OrderContext CreateDataSource()
            {
                var dataSource = new OrderContext();
                dataSource.Configuration.ProxyCreationEnabled = false;
                return dataSource;            
            }
        }
    

    //Unit Test 1 - Querying via data context directly
    public void EFDataContext_GetOrderTest()
    {            
        var context = new OrderContext();            
        var list = (from a in context.Orders 
              where a.OrderId == 10 || 
                    a.OrderId == 15 ||
                    a.OrderId== 20 select a).ToList();
    
        //CustomerInfo and ProductList values are populated properly
    }
    
    
    //Unit test 2 - Querying via OData Service
    public void OData_GetOrderTest()
    {
      string uriString = "http://localhost/OrderServices/OrderDataService.svc/Orders(10)";
      Uri serviceUri = new Uri(uriString);
      OrderContext context = new OrderContext(serviceUri);
      context.IgnoreResourceNotFoundException = true;
      var orderList = context.Orders;            
    
      foreach (Order s in orderList)
      {
         TestContext.WriteLine("OrderId=" + s.ID);
    
         Assert.IsNotNull(s.CustomerInfo);  //CustomerInfo is not returned with OData call
                                      //but it's returned properly with entity framework call.
    
         foreach (Product p in s.ProductList)
         {
            //ProductList is also not returned with OData Service call,
            //but it is returned properly when accessing through Entity Framework calls     
            //directly
         }
    
       }            
    }
    

    //app.config   
    <configuration>    
      <connectionStrings>    
        <add name="OrderContext" connectionString="a valid connection string" providerName="System.Data.SqlClient" />    
      </connectionStrings>    
    </configuration> 
    

1 个答案:

答案 0 :(得分:2)

OData(或者在本例中为WCF数据服务客户端)不会延迟加载导航属性(这是从关系创建的属性被调用的)。你必须明确地要求它。

您可以预先执行此操作,通过展开,您可以要求原始查询在导航属性的另一侧包含实体。只需在查询中添加.Expand(“订单”)即可获得订单实体以及客户。

您也可以稍后通过context.LoadProperty方法执行此操作。