这是我想要做的:
我有一个现有的数据库,我需要从中获取数据。
我创建了数据合同,通过使用Entity Framework将它们映射到各个表。在我的例子中,我有三个表 - tblOrder,tblProduct和tblCustomer。所以我创建了三个数据合同来映射到这些表。实体框架注释已添加到数据承诺中。我写了一个单元测试来测试我的数据合同。通过直接的Entity Framework调用,一切都按预期工作。见下面的单元测试1.
为每个数据协定添加了DataServiceKey批注。并通过添加订单上下文和数据服务svc将它们与OData服务包装在一起。见下文。
写了一个单元测试,通过OData服务访问一些现有的订单数据。问题:OData服务仅返回Order对象上的非自定义数据类型。它在客户数据类型字段(例如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>
答案 0 :(得分:2)
OData(或者在本例中为WCF数据服务客户端)不会延迟加载导航属性(这是从关系创建的属性被调用的)。你必须明确地要求它。
您可以预先执行此操作,通过展开,您可以要求原始查询在导航属性的另一侧包含实体。只需在查询中添加.Expand(“订单”)即可获得订单实体以及客户。
您也可以稍后通过context.LoadProperty方法执行此操作。