वेब एपीआई और ओडाटा का उपयोग करते हुए डीटीओ का उपयोग करके, मेरे पास एक सेवा है जो इकाई फ्रेमवर्क इकाइयों के बजाय डेटा ट्रांसफर ऑब्जेक्ट्स का खुलासा करती है।ओडीटा और वेब एपीआई
मैं AutoMapper का उपयोग ProjectTo()
का उपयोग कर अपने डीटीओ काउंटर भागों में एफई संस्थाओं को बदलने के लिए:
public class SalesOrdersController : ODataController
{
private DbContext _DbContext;
public SalesOrdersController(DbContext context)
{
_DbContext = context;
}
[EnableQuery]
public IQueryable<SalesOrderDto> Get(ODataQueryOptions<SalesOrderDto> queryOptions)
{
return _DbContext.SalesOrders.ProjectTo<SalesOrderDto>(AutoMapperConfig.Config);
}
[EnableQuery]
public IQueryable<SalesOrderDto> Get([FromODataUri] string key, ODataQueryOptions<SalesOrderDto> queryOptions)
{
return _DbContext.SalesOrders.Where(so => so.SalesOrderNumber == key)
.ProjectTo<SalesOrderDto>(AutoMapperConfig.Config);
}
}
AutoMapper (v4.2.1) के रूप में कॉन्फ़िगर किया गया है, ध्यान दें ExplicitExpansion()
जो क्रमबद्धता ऑटो नेविगेशन गुण का विस्तार होने से बचाता है, जब वे अनुरोध किया नहीं कर रहे हैं:
cfg.CreateMap<SalesOrderHeader, SalesOrderDto>()
.ForMember(dest => dest.SalesOrderLines, opt => opt.ExplicitExpansion());
cfg.CreateMap<SalesOrderLine, SalesOrderLineDto>()
.ForMember(dest => dest.MasterStockRecord, opt => opt.ExplicitExpansion())
.ForMember(dest => dest.SalesOrderHeader, opt => opt.ExplicitExpansion());
ExplicitExpansion()
तो एक नई समस्या जहां निम्न अनुरोध एक त्रुटि फेंकता बनाता है:
/odatademo/SalesOrders('123456')?$expand=SalesOrderLines
The query specified in the URI is not valid. The specified type member 'SalesOrderLines' is not supported in LINQ to Entities
नेविगेशन प्रॉपर्टी SalesOrderLines
ईएफ के लिए अज्ञात है, इसलिए यह त्रुटि काफी कुछ है जो मुझे होने की उम्मीद है। सवाल यह है कि, मैं इस प्रकार के अनुरोध को कैसे संभाल सकता हूं?
ProjectTo()
विधि एक अधिभार मुझे गुण है कि विस्तार की आवश्यकता होती है की एक सरणी में पारित करने के लिए अनुमति देता है कि है, मैंने पाया & संशोधित विस्तार विधि ToNavigationPropertyArray
कोशिश करते हैं और एक स्ट्रिंग सरणी में अनुरोध को पार्स करने के लिए:
[EnableQuery]
public IQueryable<SalesOrderDto> Get([FromODataUri] string key, ODataQueryOptions<SalesOrderDto> queryOptions)
{
return _DbContext.SalesOrders.Where(so => so.SalesOrderNumber == key)
.ProjectTo<SalesOrderDto>(AutoMapperConfig.Config, null, queryOptions.ToNavigationPropertyArray());
}
public static string[] ToNavigationPropertyArray(this ODataQueryOptions source)
{
if (source == null) { return new string[]{}; }
var expandProperties = string.IsNullOrWhiteSpace(source.SelectExpand?.RawExpand) ? new List<string>().ToArray() : source.SelectExpand.RawExpand.Split(',');
for (var expandIndex = 0; expandIndex < expandProperties.Length; expandIndex++)
{
// Need to transform the odata syntax for expanding properties to something EF will understand:
// OData may pass something in this form: "SalesOrderLines($expand=MasterStockRecord)";
// But EF wants it like this: "SalesOrderLines.MasterStockRecord";
expandProperties[expandIndex] = expandProperties[expandIndex].Replace(" ", "");
expandProperties[expandIndex] = expandProperties[expandIndex].Replace("($expand=", ".");
expandProperties[expandIndex] = expandProperties[expandIndex].Replace(")", "");
}
var selectProperties = source.SelectExpand == null || string.IsNullOrWhiteSpace(source.SelectExpand.RawSelect) ? new List<string>().ToArray() : source.SelectExpand.RawSelect.Split(',');
//Now do the same for Select (incomplete)
var propertiesToExpand = expandProperties.Union(selectProperties).ToArray();
return propertiesToExpand;
}
इस विस्तार के लिए काम करता है, इसलिए अब मैं निम्नलिखित की तरह एक अनुरोध को पूरा कर सकते हैं:
/odatademo/SalesOrders('123456')?$expand=SalesOrderLines
या की तरह एक और अधिक जटिल अनुरोध:
/odatademo/SalesOrders('123456')?$expand=SalesOrderLines($expand=MasterStockRecord)
हालांकि, और अधिक जटिल अनुरोध है कि $ गठबंधन $ के साथ चयन करने के लिए विस्तार की कोशिश विफल हो जाएगा:
/odatademo/SalesOrders('123456')?$expand=SalesOrderLines($select=OrderQuantity)
Sequence contains no elements
तो, सवाल है: मैं इस सही तरीके से आ रहा हूँ? यह बहुत गंध महसूस करता है कि मुझे समझने के लिए कुछ लिखना होगा और ODataQueryOptions को कुछ ईएफ समझने में बदलना होगा।
ऐसा लगता है यह एक नहीं बल्कि लोकप्रिय विषय है:
- odata-expand-dtos-and-entity-framework
- how-to-specify-the-shape-of-results-with-webapi2-odata-with-expand
- web-api-queryable-how-to-apply-automapper
- how-do-i-map-an-odata-query-against-a-dto-to-another-entity
हालांकि इनमें से अधिकांश ProjectTo
उपयोग करने का सुझाव, कोई भी पता करने के लिए लग रहे हैं serialization ऑटो expan ExplictExpansion
को कॉन्फ़िगर किया गया है, या विस्तार को संभालने के लिए कैसे करें।
वर्ग और नीचे कॉन्फ़िग:
इकाई की रूपरेखा (V6.1.3) संस्थाओं:
public class SalesOrderHeader
{
public string SalesOrderNumber { get; set; }
public string Alpha { get; set; }
public string Customer { get; set; }
public string Status { get; set; }
public virtual ICollection<SalesOrderLine> SalesOrderLines { get; set; }
}
public class SalesOrderLine
{
public string SalesOrderNumber { get; set; }
public string OrderLineNumber { get; set; }
public string Product { get; set; }
public string Description { get; set; }
public decimal OrderQuantity { get; set; }
public virtual SalesOrderHeader SalesOrderHeader { get; set; }
public virtual MasterStockRecord MasterStockRecord { get; set; }
}
public class MasterStockRecord
{
public string ProductCode { get; set; }
public string Description { get; set; }
public decimal Quantity { get; set; }
}
OData (V6.13।0) डाटा ट्रांसफर वस्तुओं:
public class SalesOrderDto
{
[Key]
public string SalesOrderNumber { get; set; }
public string Customer { get; set; }
public string Status { get; set; }
public virtual ICollection<SalesOrderLineDto> SalesOrderLines { get; set; }
}
public class SalesOrderLineDto
{
[Key]
[ForeignKey("SalesOrderHeader")]
public string SalesOrderNumber { get; set; }
[Key]
public string OrderLineNumber { get; set; }
public string LineType { get; set; }
public string Product { get; set; }
public string Description { get; set; }
public decimal OrderQuantity { get; set; }
public virtual SalesOrderDto SalesOrderHeader { get; set; }
public virtual StockDto MasterStockRecord { get; set; }
}
public class StockDto
{
[Key]
public string StockCode { get; set; }
public string Description { get; set; }
public decimal Quantity { get; set; }
}
OData कॉन्फ़िग:
var builder = new ODataConventionModelBuilder();
builder.EntitySet<StockDto>("Stock");
builder.EntitySet<SalesOrderDto>("SalesOrders");
builder.EntitySet<SalesOrderLineDto>("SalesOrderLines");
हाय डेव एक सूची प्रदान करेगा। उपर्युक्त कोड उस कोड को दिखाता है जिसका उपयोग मैं इसे कॉन्फ़िगर करने के लिए करता हूं और ओडाटा को पार्स करने के लिए करता हूं ताकि यह पता चल सके कि कौन से नेविगेशन गुणों को विस्तार की आवश्यकता है। यह 'ToNavigationPropertyArray()' एक्सटेंशन विधि का उद्देश्य है, जिसके परिणामस्वरूप 'ProjectTo() 'को पास किया जाता है। मेरा प्रश्न था/ओडाटा क्वेरी स्ट्रिंग को पार्स करने के लिए एक्सटेंशन विधि का उपयोग करना सही दृष्टिकोण था क्योंकि एकाधिक नेविगेशन गुणों को विस्तार करने की आवश्यकता होने पर यह गन्दा हो जाता है। मैंने अधिक जटिल प्रश्नों के लिए कार्यों और कार्यों का उपयोग करके इसके आसपास काम किया। – philreed