JSON और इकाई के साथ परिपत्र संदर्भ समस्या के आसपास कैसे प्राप्त करें


13

मैं अपनी प्रस्तुति परत और डेटा मॉडल / डेटाबेस के लिए इकाई ढांचे के लिए JSON के साथ MVC का लाभ उठाने वाली एक वेबसाइट बनाने के साथ प्रयोग कर रहा हूं। मेरा मुद्दा JSON में मेरी मॉडल वस्तुओं को क्रमबद्ध करने के साथ आता है।

मैं अपने डेटाबेस को बनाने के लिए कोड पहली विधि का उपयोग कर रहा हूं। कोड करते समय पहली विधि एक से कई संबंधों (माता-पिता / बच्चे) के लिए आवश्यक होती है कि बच्चे को माता-पिता के पास वापस भेजना चाहिए। (उदाहरण कोड मेरे एक टाइपो हो, लेकिन आप चित्र प्राप्त करें)

class parent
{
   public List<child> Children{get;set;}
   public int Id{get;set;}

}
class child
{
    public int ParentId{get;set;}
    [ForeignKey("ParentId")]
    public parent MyParent{get;set;}
    public string name{get;set;}
 }

जब एक "माता-पिता" ऑब्जेक्ट को JsonResult के माध्यम से लौटाते हैं तो एक परिपत्र संदर्भ त्रुटि फेंक दी जाती है क्योंकि "बच्चे" में कक्षा माता-पिता की संपत्ति होती है।

मैंने ScriptIgnore विशेषता की कोशिश की है, लेकिन मैं बच्चे की वस्तुओं को देखने की क्षमता खो देता हूं। मुझे कुछ बिंदु पर एक पैरेंट चाइल्ड व्यू में जानकारी प्रदर्शित करने की आवश्यकता होगी।

मैंने माता-पिता और बच्चे दोनों के लिए आधार कक्षाएं बनाने की कोशिश की है जिनके पास एक परिपत्र संदर्भ नहीं है। दुर्भाग्य से जब मैं बेसपरेंट और बेसहिल भेजने की कोशिश करता हूं तो इन्हें JSON Parser द्वारा उनकी व्युत्पन्न कक्षाओं के रूप में पढ़ा जाता है (मुझे पूरा यकीन है कि यह अवधारणा मुझसे बच रही है)।

Base.baseParent basep = (Base.baseParent)parent;
return Json(basep, JsonRequestBehavior.AllowGet);

एक समाधान जो मैं लेकर आया हूं, वह है "व्यू" मॉडल बनाना। मैं डेटाबेस मॉडल के सरल संस्करण बनाता हूं जिसमें मूल वर्ग का संदर्भ शामिल नहीं है। ये दृश्य मॉडल प्रत्येक के पास डेटाबेस संस्करण और एक कंस्ट्रक्टर को वापस लाने की विधि है जो डेटाबेस मॉडल को एक पैरामीटर (viewmodel.name = databasemodel.name) के रूप में लेता है। यह विधि मजबूर लगती है हालांकि यह काम करती है।

नोट: मैं यहाँ पोस्ट कर रहा हूँ क्योंकि मुझे लगता है कि यह अधिक चर्चा योग्य है। मैं इस मुद्दे पर आने के लिए एक अलग डिजाइन पैटर्न का लाभ उठा सकता हूं या यह मेरे मॉडल पर एक अलग विशेषता का उपयोग करने के रूप में सरल हो सकता है। अपनी खोज में मैंने इस समस्या को दूर करने के लिए एक अच्छी विधि नहीं देखी है।

मेरा अंतिम लक्ष्य एक अच्छा MVC एप्लिकेशन होगा जो सर्वर के साथ संचार करने और डेटा प्रदर्शित करने के लिए JSON का भारी लाभ उठाता है। परतों के पार एक सुसंगत मॉडल को बनाए रखते हुए (या सबसे अच्छा के रूप में मैं साथ आ सकते हैं)।

जवाबों:


6

मुझे आपके प्रश्न में दो अलग-अलग विषय दिखाई देते हैं:

  • JSON पर क्रमबद्ध करते समय परिपत्र संदर्भ कैसे प्रबंधित करें?
  • आपके विचार में ईएफ संस्थाओं को मॉडल संस्थाओं के रूप में उपयोग करना कितना सुरक्षित है?

परिपत्र संदर्भों के बारे में मुझे यह कहते हुए खेद है कि कोई सरल समाधान नहीं है। पहला क्योंकि JSON का उपयोग परिपत्र संदर्भों को दर्शाने के लिए नहीं किया जा सकता है, निम्नलिखित कोड:

var aParent = {Children : []}, aChild  = {Parent : aParent};
aParent.Children.push(aChild);
JSON.stringify(aParent);

का परिणाम: TypeError: Converting circular structure to JSON

आपके पास एकमात्र विकल्प केवल कंपोजिशन -> कंपोनेंट के कंपोनेंट पार्ट को रखना है और "बैक नेविगेशन" कंपोनेंट को छोड़ना है -> कंपोजिट, इस प्रकार आप उदाहरण में:

class parent
{
    public List<child> Children{get;set;}
    public int Id{get;set;}
}
class child
{
    public int ParentId{get;set;}
    [ForeignKey("ParentId"), ScriptIgnore]
    public parent MyParent{get;set;}
    public string name{get;set;}
}

आपके jQuery के उपयोग से, इस नेविगेशन प्रॉपर्टी को आपके ग्राहक की ओर से पुनः प्राप्त करने से कुछ भी नहीं रोकता है:

$.each(parent.Children, function(i, child) {
  child.Parent = parent;  
})

लेकिन तब आपको इसे सर्वर पर वापस भेजने से पहले इसे फिर से त्यागना होगा, JSON.stringify के लिए परिपत्र संदर्भ को क्रमबद्ध करने में सक्षम नहीं होगा:

$.each(parent.Children, function(i, child) {
  delete child.Parent;  
})

अब आपके विचार मॉडल संस्थाओं के रूप में ईएफ संस्थाओं का उपयोग करने का मुद्दा है।

पहले ईएफ आपके वर्ग के डायनेमिक प्रॉक्सी का उपयोग करने की संभावना है जैसे कि परिवर्तन का पता लगाने या आलसी लोडिंग जैसे व्यवहारों को लागू करने के लिए, यदि आप ईएफ संस्थाओं को अनुक्रमित करना चाहते हैं तो आपको उन्हें निष्क्रिय करना होगा।

इसके अलावा, यूआई में ईएफ संस्थाओं का उपयोग करने से जोखिम हो सकता है क्योंकि सभी डिफ़ॉल्ट बाइंडर अनुरोधों से हर क्षेत्र को उन क्षेत्रों में मैप करेंगे, जिनमें आप उपयोगकर्ता को सेट नहीं करना चाहते थे।

इस प्रकार, यदि आप चाहते हैं कि आप एमवीसी ऐप को ठीक से डिज़ाइन करें तो मैं आपके आंतरिक व्यापार मॉडल के "कण्ठ" को ग्राहक के संपर्क में आने से रोकने के लिए एक समर्पित दृश्य मॉडल का उपयोग करने की सिफारिश करूंगा, इस प्रकार मैं आपको एक विशिष्ट दृश्य मॉडल की सिफारिश करूंगा।


क्या वस्तु उन्मुख तकनीकों के साथ एक फैंसी तरीका है जो मुझे परिपत्र संदर्भ और ईएफ मुद्दे दोनों के आसपास मिल सकता है।
दानस्कन २ Dan

क्या वस्तु उन्मुख तकनीकों के साथ एक फैंसी तरीका है जो मुझे परिपत्र संदर्भ और ईएफ मुद्दे दोनों के आसपास मिल सकता है? जैसे BaseObject को UnitObject द्वारा और viewObject द्वारा विरासत में मिला है। तो UnitObject में गोलाकार संदर्भ होगा लेकिन viewObject में परिपत्र संदर्भ नहीं होगा। मैं इस से दृश्य के निर्माण के लिए मिल गया है। से बाहर निकलें ।OOject (viewObject.name = unitObject.name) से लेकिन यह समय की बर्बादी लगती है। मैं इस मुद्दे पर कैसे पहुँच सकता हूँ?
दानस्कन २ Dan

वे आपको बहुत पसंद करते हैं। आपकी व्याख्या बहुत स्पष्ट और समझने में आसान थी।
निक

2

वस्तुओं को क्रमबद्ध करने के प्रयास का एक सरल विकल्प माता-पिता / बच्चे की वस्तुओं के क्रमांकन को अक्षम करना होगा। इसके बजाय, आप संबंधित माता-पिता / बाल वस्तुओं को अपनी आवश्यकता के अनुसार लाने के लिए एक अलग कॉल कर सकते हैं। यह आपके आवेदन के लिए आदर्श नहीं हो सकता है, लेकिन यह एक विकल्प है।

ऐसा करने के लिए, आप एक DataContractSerializer सेट कर सकते हैं और अपने डेटा मॉडल वर्ग के निर्माता में 'false' के लिए DataContractSerializer.PreserveObjectReferences गुण सेट कर सकते हैं। यह निर्दिष्ट करता है कि HTTP प्रतिक्रियाओं को क्रमबद्ध करने पर ऑब्जेक्ट संदर्भों को संरक्षित नहीं किया जाना चाहिए।

उदाहरण:

Json प्रारूप:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = 
    Newtonsoft.Json.PreserveReferencesHandling.None;

XML प्रारूप:

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
var dcs = new DataContractSerializer(typeof(Employee), null, int.MaxValue, 
    false, /* preserveObjectReferences: */ false, null);
xml.SetSerializer<Employee>(dcs);

इसका मतलब यह है कि यदि आप एक ऐसी वस्तु प्राप्त करते हैं जिसमें बाल वस्तुओं का उल्लेख है, तो बाल वस्तुओं को क्रमबद्ध नहीं किया जाएगा।

DataContractsSerializer वर्ग भी देखें ।


1

JSON धारावाहिक जो परिपत्र संदर्भों से संबंधित है

यहाँ एक उदाहरण कस्टम जैक्सन है JSONSerializerजो पहली घटना को क्रमबद्ध करके और referenceबाद की सभी घटनाओं पर * पहली घटना को संग्रहीत करके परिपत्र संदर्भों से संबंधित है।

जैक्सन के साथ वस्तुओं को सीरियल करते समय परिपत्र संदर्भों से निपटना

उपरोक्त लेख से प्रासंगिक आंशिक स्निपेट:

private final Set<ObjectName> seen;

/**
 * Serialize an ObjectName with all its attributes or only its String representation if it is a circular reference.
 * @param on ObjectName to serialize
 * @param jgen JsonGenerator to build the output
 * @param provider SerializerProvider
 * @throws IOException
 * @throws JsonProcessingException
 */
@Override
public void serialize(@Nonnull final ObjectName on, @Nonnull final JsonGenerator jgen, @Nonnull final SerializerProvider provider) throws IOException, JsonProcessingException
{
    if (this.seen.contains(on))
    {
        jgen.writeString(on.toString());
    }
    else
    {
        this.seen.add(on);
        jgen.writeStartObject();
        final List<MBeanAttributeInfo> ais = this.getAttributeInfos(on);
        for (final MBeanAttributeInfo ai : ais)
        {
            final Object attribute = this.getAttribute(on, ai.getName());
            jgen.writeObjectField(ai.getName(), attribute);
        }
        jgen.writeEndObject();
    }
}

0

एक समाधान जो मैं लेकर आया हूं, वह है "व्यू" मॉडल बनाना। मैं डेटाबेस मॉडल के सरल संस्करण बनाता हूं जिसमें मूल वर्ग का संदर्भ शामिल नहीं है। ये दृश्य मॉडल प्रत्येक के पास डेटाबेस संस्करण और एक कंस्ट्रक्टर को वापस लाने की विधि है जो डेटाबेस मॉडल को एक पैरामीटर (viewmodel.name = databasemodel.name) के रूप में लेता है। यह विधि मजबूर लगती है हालांकि यह काम करती है।

नंगे न्यूनतम डेटा को भेजना एकमात्र सही उत्तर है। जब आप डेटाबेस से डेटा भेजते हैं, तो आमतौर पर सभी संघों के साथ हर एक कॉलम को भेजने का कोई मतलब नहीं होता है। उपभोक्ताओं को डेटाबेस संघों और संरचनाओं से निपटने की आवश्यकता नहीं होनी चाहिए, जो डेटाबेस के लिए है। इससे न केवल बैंडविड्थ की बचत होगी बल्कि इसे बनाए रखना, पढ़ना और उपभोग करना भी बहुत आसान है। डेटा को क्वेरी करें और फिर उसे मॉडल बनाएं जिसे आपको वास्तव में eq भेजने की आवश्यकता है। न्यूनतम।


जब आप बड़े डेटा के बारे में बात कर रहे हों, तो अधिक प्रसंस्करण समय की आवश्यकता होती है, क्योंकि अब आपको दो बार सब कुछ बदलना होगा।
डेविड वैन डुगटरन

-2

.Include(x => x.TableName ) रिश्तों को नहीं लौटाना (प्रिंसिपल टेबल से डिपेंडेंट टेबल तक), या डेटा की केवल एक पंक्ति को वापस करना, FIX HERE:

/programming/43127957/include-not-working-in-net-core-returns-one-parent

इसके अलावा, Startup.cs में यह सुनिश्चित करें कि आपके पास सबसे ऊपर है:

using Microsoft.EntityFrameworkCore; 
using Newtonsoft.Json; 
using Project_Name_Here.Models;

बेटा वाट? erm .. वाट?
amels
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.