2011-06-30 137 views
0

這是我想做的事:OData服務不定製返回對象

  1. 我從那裏我需要得到數據的現有數據庫。

  2. 我創建了數據契約,通過使用實體框架將它們映射到相應的表。在我的例子中,我有三個表 - tblOrder,tblProduct和tblCustomer。所以我創建了三個數據契約映射到這些表。實體框架註釋已添加到數據對照中。我寫了一個單元測試來測試我的數據合同。一切都按照預期使用直接的實體框架調用。請參閱下面的單元測試1。

  3. 爲每個數據合同添加了DataServiceKey註釋。並通過添加訂單上下文和數據服務svc將它們包裝在OData服務中。見下文。

  4. 寫了一個單元測試,通過OData服務訪問一些現有的訂單數據。問題:OData服務僅返回Order對象上的非自定義數據類型。它在custome數據類型字段(如CustomerInfo和ProductList)上返回null。

我做錯了什麼?對於使用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> 

回答

2

的OData(或在這種情況下,WCF數據服務客戶端)不延遲加載導航性能(這是什麼從關係創建的屬性是所謂的)。你必須明確地要求。

您可以通過展開來做到這一點,您可以在其中要求原始查詢將實體包含在導航屬性的另一側。只需將.Expand(「訂單」)添加到您的查詢中即可獲得訂單實體以及客戶。

您也可以稍後通過context.LoadProperty方法執行此操作。

+0

這個問題似乎在於我們將ProxyCreationEnabled設置爲false,如果我們在我們的簡單數據訪問單元測試中這樣做,訂單不再加載。我們已經嘗試使用Expand選項已經和LazyLoadingEnabled = false一起使用,但是我們仍然沒有獲得Expand,如果我們將ProxyCreationEnabled變回true,那麼URL將不再拉上來。我們如何強制EF加載訂單而不將ProxyCreationEnabled設置爲true? – dariusriggins

+0

也嘗試應用此修補程序,但它沒有解決問題,如果我離開代理生成。 http://support.microsoft.com/kb/2277657 – dariusriggins

+0

你可以嘗試追蹤線路上的請求/響應,例如使用fiddler來查看響應是否包含擴展的實體(假設您使用客戶)? –