'সাবসোনিক.সেকিমা। ডেটাবেস কলম' টাইপের কোনও অবজেক্টকে সিরিয়ালাইজ করার সময় একটি বিজ্ঞপ্তিযুক্ত রেফারেন্স সনাক্ত করা হয়েছিল।


170

আমি একটি সাধারণ জেএসএন রিটার্ন করার চেষ্টা করছি তবে আমার নীচে নিম্নলিখিত বিষয়গুলি রয়েছে।

public JsonResult GetEventData()
{
    var data = Event.Find(x => x.ID != 0);
    return Json(data);
}

এই প্রশ্নের শিরোনামে ব্যতিক্রম হিসাবে আমি একটি এইচটিটিপি 500 পাই। আমিও চেষ্টা করেছি

var data = Event.All().ToList()

যে একই সমস্যা দিয়েছে।

এটি কি বাগ বা আমার বাস্তবায়ন?


1
এটার দিকে তাকান. ScriptIgnoreঅ্যাট্রিবিউটটি ব্যবহার করে একটি সমাধান রয়েছে । stackoverflow.com/questions/1193857/subsonic-3-0-0-2-structs-tt
freddoo

এটি ছিল আমার পক্ষে সেরা সমাধান; আমি গেম> টুর্নামেন্ট> গেম> টুর্নামেন্ট> গেম ইত্যাদি পেয়েছিলাম আমি টুর্নামেন্টে একটি ScriptIgnoreবৈশিষ্ট্য রেখেছি ame গেম সম্পত্তি এবং এটি দুর্দান্ত কাজ করেছে :)
এথ0

যদি কেউ এই সমস্যার জন্য "অটোমেটেড" (সেরা-অনুশীলন নয়) সমাধান চায় তবে অতিরিক্ত কোডের প্রয়োজন নেই, এই
প্রশ্নটি দেখুন: জেএসএনে

উত্তর:


175

দেখে মনে হচ্ছে আপনার অবজেক্টের শ্রেণিবিন্যাসে বিজ্ঞপ্তি সংক্রান্ত রেফারেন্স রয়েছে যা জেএসএন সিরিয়ালাইজার সমর্থন করে না। আপনার কি সমস্ত কলাম দরকার? আপনি কেবলমাত্র ভিউতে প্রয়োজনীয় বৈশিষ্ট্যগুলি বেছে নিতে পারেন:

return Json(new 
{  
    PropertyINeed1 = data.PropertyINeed1,
    PropertyINeed2 = data.PropertyINeed2
});

এটি আপনার JSON অবজেক্টটিকে হালকা এবং বুঝতে সহজ করে তুলবে। আপনার যদি অনেক বৈশিষ্ট্য থাকে তবে ডিটিও অবজেক্ট এবং অবজেক্টের মধ্যে স্বয়ংক্রিয়ভাবে ম্যাপ করতে অটোম্যাপার ব্যবহার করা যেতে পারে ।


আমি হয়তো বেশী আমি আমি মনে করি যে সার্কুলার রেফারেন্স কারণ ইভেন্ট আমি IQueryable রয়েছে <শ্রেণী> যেটা ঘুরে ফিরে একটি IQueryable <ইভেন্ট> থাকবে কাজ করতে পারে চান নির্বাচন মনে
জন

7
অটোম্যাপার কোনও গ্যারান্টি নয় যে আপনি এই সমস্যাটি পাবেন না। আমি এখানে একটি উত্তর খুঁজতে এসেছি এবং আমি আসলে অটোম্যাপার ব্যবহার করছি।
ক্যাপ্টেন কেনপাচি

1
@ ক্লেকাবুমের উত্তরটি কীভাবে এটি বিজ্ঞপ্তি হতে পারে তা ব্যাখ্যা করে দেখুন
পান্ডাউড

106

আমি একই সমস্যা ছিল এবং দ্বারা সমাধান করা using Newtonsoft.Json;

var list = JsonConvert.SerializeObject(model,
    Formatting.None,
    new JsonSerializerSettings() {
        ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
});

return Content(list, "application/json");

3
এই ইনলাইন কোডটি আমার পক্ষে ভাল কাজ করেছে। ক্রাভিট ৮৮ দ্বারা উল্লিখিত গ্লোবাল কনফিগারেশনের একই জিনিসগুলি আমার পক্ষে কাজ করছে না। এছাড়াও, এই কোডের জন্য সামগ্রী ফলাফল ফেরত দিতে পদ্ধতির স্বাক্ষরটি আপডেট করা উচিত।
বিএল

6
এটি সেরা উত্তর হিসাবে চিহ্নিত করা উচিত, কারণ এটি এমন ক্ষেত্রে জুড়েছে যে আপনি গ্রহণযোগ্য হিসাবে চিহ্নিত উত্তর হিসাবে আপনার অবজেক্টগুলিকে অন্যান্য উপস্থাপনে রূপান্তর করতে ঘন্টা ব্যয় করতে পারবেন না।
রেনান

56

এটি প্রকৃতপক্ষে ঘটেছিল কারণ জটিল বস্তুগুলি ফলে জেসন অবজেক্টকে ব্যর্থ করে তোলে। এবং এটি ব্যর্থ হয় কারণ যখন বস্তুটি ম্যাপ করা হয় তখন এটি শিশুদের মানচিত্র করে, যা তাদের পিতামাতাকে ম্যাপ করে, যা ঘটনার জন্য একটি বিজ্ঞপ্তিযুক্ত রেফারেন্স তৈরি করে। জেসন এটির ক্রমিকায়িত করতে অসীম সময় নিবে, সুতরাং এটি ব্যতিক্রম বাদ দিয়ে সমস্যাটি প্রতিরোধ করে।

সত্তা ফ্রেমওয়ার্ক ম্যাপিং একই আচরণ তৈরি করে এবং সমাধানটি হ'ল সমস্ত অযাচিত বৈশিষ্ট্যগুলি বাতিল করা।

কেবল চূড়ান্ত উত্তরের ব্যাখ্যা দিলে, পুরো কোডটি হ'ল:

public JsonResult getJson()
{
    DataContext db = new DataContext ();

    return this.Json(
           new {
                Result = (from obj in db.Things select new {Id = obj.Id, Name = obj.Name})
               }
           , JsonRequestBehavior.AllowGet
           );
}

আপনি কোনও Resultসম্পত্তির ভিতরে থাকা জিনিসগুলি না চাইলে এটি নিম্নলিখিতও হতে পারে :

public JsonResult getJson()
{
    DataContext db = new DataContext ();

    return this.Json(
           (from obj in db.Things select new {Id = obj.Id, Name = obj.Name})
           , JsonRequestBehavior.AllowGet
           );
}

1
পরিষ্কার এবং সহজ জিনিসগুলি বোঝার জন্য +1, ধন্যবাদ @ ক্লে। আমি ত্রুটির পিছনে ধারণাগুলি সম্পর্কে আপনার ব্যাখ্যা পছন্দ করি।
অজয় 2707

14

জিনিসগুলি সংক্ষেপে বলতে গেলে এর 4 টি সমাধান রয়েছে:

সমাধান 1: DBContext এর জন্য প্রক্সিক্রিয়েশন বন্ধ করুন এবং শেষ পর্যন্ত এটি পুনরুদ্ধার করুন।

    private DBEntities db = new DBEntities();//dbcontext

    public ActionResult Index()
    {
        bool proxyCreation = db.Configuration.ProxyCreationEnabled;
        try
        {
            //set ProxyCreation to false
            db.Configuration.ProxyCreationEnabled = false;

            var data = db.Products.ToList();

            return Json(data, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
            return Json(ex.Message);
        }
        finally
        {
            //restore ProxyCreation to its original state
            db.Configuration.ProxyCreationEnabled = proxyCreation;
        }
    }

সমাধান 2: সিরিয়ালাইজার সেটিংসে উপেক্ষা করার জন্য রেফারেন্সলুপ হ্যান্ডলিং সেট করে জসনকন্ট ব্যবহার করুন।

    //using using Newtonsoft.Json;

    private DBEntities db = new DBEntities();//dbcontext

    public ActionResult Index()
    {
        try
        {
            var data = db.Products.ToList();

            JsonSerializerSettings jss = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
            var result = JsonConvert.SerializeObject(data, Formatting.Indented, jss);

            return Json(result, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
            return Json(ex.Message);
        }
    }

দুটি সমাধান অনুসরণ করা একই, তবে একটি মডেল ব্যবহার করা ভাল কারণ এটি শক্ত টাইপযুক্ত।

সমাধান 3: একটি মডেল ফিরিয়ে দিন যার মধ্যে কেবল প্রয়োজনীয় বৈশিষ্ট্য অন্তর্ভুক্ত রয়েছে।

    private DBEntities db = new DBEntities();//dbcontext

    public class ProductModel
    {
        public int Product_ID { get; set;}

        public string Product_Name { get; set;}

        public double Product_Price { get; set;}
    }

    public ActionResult Index()
    {
        try
        {
            var data = db.Products.Select(p => new ProductModel
                                                {
                                                    Product_ID = p.Product_ID,
                                                    Product_Name = p.Product_Name,
                                                    Product_Price = p.Product_Price
                                                }).ToList();

            return Json(data, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
            return Json(ex.Message);
        }
    }

সমাধান 4: একটি নতুন গতিশীল অবজেক্ট ফিরিয়ে দিন যার মধ্যে কেবল প্রয়োজনীয় বৈশিষ্ট্য অন্তর্ভুক্ত রয়েছে।

    private DBEntities db = new DBEntities();//dbcontext

    public ActionResult Index()
    {
        try
        {
            var data = db.Products.Select(p => new
                                                {
                                                    Product_ID = p.Product_ID,
                                                    Product_Name = p.Product_Name,
                                                    Product_Price = p.Product_Price
                                                }).ToList();

            return Json(data, JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
            return Json(ex.Message);
        }
    }

7

জেএসএন, এক্সএমএল এবং অন্যান্য বিভিন্ন ফর্ম্যাটের মতো একটি গাছ ভিত্তিক সিরিয়ালাইজেশন ফর্ম্যাট। আপনার গাছগুলিতে বিজ্ঞপ্তি উল্লেখ থাকলে এটি আপনাকে ভালোবাসবে না, যেমন "গাছ" হ'ল:

root B => child A => parent B => child A => parent B => ...

নির্দিষ্ট পথ ধরে প্রায়শই নেভিগেশন নিষ্ক্রিয় করার উপায় রয়েছে; উদাহরণস্বরূপ, আপনার সাথে XmlSerializerপিতামাত সম্পত্তি হিসাবে চিহ্নিত করতে পারে XmlIgnore। আমি জানি না যে প্রশ্নে জসন সিরিয়ালাইজারের মাধ্যমে এটি সম্ভব কিনা, অথবা DatabaseColumnউপযুক্ত চিহ্নিতকারীও রয়েছে কিনা ( খুব কমই সম্ভব, কারণ এটি প্রতিটি সিরিয়ালাইজেশন এপিআইয়ের উল্লেখ করতে হবে)


4

এটি নতুন DbContext টি 4 টেমপ্লেটের কারণে যা অ্যান্টিটি ফ্রেমওয়ার্ক সত্তা তৈরি করার জন্য ব্যবহৃত হয়। পরিবর্তন ট্র্যাকিং সম্পাদন করতে সক্ষম হতে, এই টেমপ্লেটগুলি আপনার সুন্দর পোকোগুলিকে মোড়ানো করে প্রক্সি প্যাটার্ন ব্যবহার করে। এটি তখন জাভাস্ক্রিপ্টসরিয়ালাইজারের সাথে সিরিয়াল করার সময় সমস্যাগুলি সৃষ্টি করে।

সুতরাং 2 সমাধানগুলি হ'ল:

  1. হয় আপনি কেবল সিরিয়ালাইজ করুন এবং ক্লায়েন্টের জন্য আপনার প্রয়োজনীয় বৈশিষ্ট্যগুলি ফিরিয়ে দিন
  2. প্রক্সির কনফিগারেশনে সেট করে আপনি প্রক্সিগুলির স্বয়ংক্রিয় জেনারেশনটি স্যুইচ করতে পারেন

    প্রসঙ্গ। কনফিগারেশন.প্রক্সি ক্রিয়েশনএনবলড = মিথ্যা;

নীচের নিবন্ধে খুব ভাল ব্যাখ্যা করা হয়েছে।

http://juristr.com/blog/2011/08/javascriptserializer-circular-reference/


4

নিউটনসফট.জসন ব্যবহার করে: আপনার গ্লোবাল.অ্যাক্স অ্যাপ্লিকেশন_সার্ট পদ্ধতিতে এই লাইনটি যুক্ত করুন:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

1
দৃশ্যত খুব সোজা এগিয়ে দেখায় তবে আমার পক্ষে কাজ করেনি
বিএল

4

[JsonIgnore]আপনার মডেল মধ্যে ভার্চুয়াল বৈশিষ্ট্য যুক্ত করুন ।


4

টেবিল অবজেক্টটি সরাসরি রূপান্তর করা থেকে বিরত থাকুন। যদি সম্পর্কগুলি অন্য টেবিলের মধ্যে সেট করা থাকে তবে এটি এই ত্রুটিটিকে ফেলে দিতে পারে। পরিবর্তে, আপনি একটি মডেল বর্গ তৈরি করতে পারেন, শ্রেণীর অবজেক্টের মান নির্ধারণ করতে পারেন এবং তারপরে এটি ক্রমিক করে তোলা যেতে পারেন।


3

প্রদত্ত উত্তরগুলি ভাল, তবে আমি মনে করি একটি "আর্কিটেকচারাল" দৃষ্টিভঙ্গি যুক্ত করে এগুলি উন্নত করা যেতে পারে।

তদন্ত

MVC's Controller.Jsonফাংশনটি কাজটি করছে তবে এই ক্ষেত্রে প্রাসঙ্গিক ত্রুটি সরবরাহ করা খুব খারাপ poor ব্যবহার করে Newtonsoft.Json.JsonConvert.SerializeObject, ত্রুটিটি নির্দিষ্ট করে ঠিক কী সেই সম্পত্তি যা বিজ্ঞপ্তি রেফারেন্সকে ট্রিগার করে। আরও জটিল বস্তু শ্রেণিবিন্যাসকে সিরিয়ালকরণ করার সময় এটি বিশেষত কার্যকর।

সঠিক স্থাপত্য

কখনই ডেটা মডেলগুলিকে সিরিয়ালাইজ করার চেষ্টা করা উচিত নয় (উদাঃ ইএফ মডেলগুলি), কারণ সিরিয়ালকরণের ক্ষেত্রে ওআরএমের নেভিগেশন বৈশিষ্ট্যগুলি ধ্বংসের পথে। ডেটা ফ্লো নিম্নলিখিত হওয়া উচিত:

Database -> data models -> service models -> JSON string 

অটো ম্যাপারগুলি (যেমন অটোম্যাপার ) ব্যবহার করে ডেটা মডেলগুলি থেকে পরিষেবা মডেলগুলি পাওয়া যায় । যদিও এটি বিজ্ঞপ্তিযুক্ত রেফারেন্সের অভাবের গ্যারান্টি দেয় না, উপযুক্ত ডিজাইনের মাধ্যমে এটি করা উচিত: পরিষেবা মডেলগুলিতে পরিষেবা ভোক্তার যা প্রয়োজন (যেমন বৈশিষ্ট্যগুলি) ঠিক তা ধারণ করা উচিত।

এই বিরল ক্ষেত্রে, ক্লায়েন্ট যখন বিভিন্ন স্তরে একই অবজেক্টের সাথে জড়িত একটি শ্রেণিবিন্যাসের জন্য অনুরোধ করে, পরিষেবাটি পিতা-মাতার>> সন্তানের সম্পর্কের সাথে একটি লিনিয়ার কাঠামো তৈরি করতে পারে (কেবল সনাক্তকারী ব্যবহার করে, উল্লেখগুলি নয়)।

আধুনিক অ্যাপ্লিকেশনগুলি একবারে জটিল ডেটা স্ট্রাকচার লোড করা এড়ায় এবং পরিষেবা মডেলগুলি পাতলা হওয়া উচিত। উদাহরণ:

  1. একটি ইভেন্ট অ্যাক্সেস করুন - কেবল শিরোনামের ডেটা (শনাক্তকারী, নাম, তারিখ ইত্যাদি) লোড করা হয় -> পরিষেবা মডেল (জেএসএন) কেবলমাত্র শিরোনাম ডেটা থাকে
  2. পরিচালিত উপস্থিতদের তালিকা - একটি পপআপ অ্যাক্সেস করুন এবং অলস লোডের তালিকায় -> পরিষেবা মডেল (জেএসওএন) কেবল উপস্থিতদের তালিকাসহ

1

আমি ফিক্সটি ব্যবহার করছি, কারণ এমভিসি 5 ভিউতে নকআউট ব্যবহার করছি।

কর্মের উপর

return Json(ModelHelper.GetJsonModel<Core_User>(viewModel));

ক্রিয়া

   public static TEntity GetJsonModel<TEntity>(TEntity Entity) where TEntity : class
    {
        TEntity Entity_ = Activator.CreateInstance(typeof(TEntity)) as TEntity;
        foreach (var item in Entity.GetType().GetProperties())
        {
            if (item.PropertyType.ToString().IndexOf("Generic.ICollection") == -1 && item.PropertyType.ToString().IndexOf("SaymenCore.DAL.") == -1)
                item.SetValue(Entity_, Entity.GetPropValue(item.Name));
        }
        return Entity_;  
    }

0

বিজ্ঞপ্তি রেফারেন্সের জন্য এমন বৈশিষ্ট্যগুলি আপনি লক্ষ্য করতে পারেন। তারপরে আপনি এর মতো কিছু করতে পারেন:

private Object DeCircular(Object object)
{
   // Set properties that cause the circular reference to null

   return object
}

-1
//first: Create a class as your view model

public class EventViewModel 
{
 public int Id{get;set}
 public string Property1{get;set;}
 public string Property2{get;set;}
}
//then from your method
[HttpGet]
public async Task<ActionResult> GetEvent()
{
 var events = await db.Event.Find(x => x.ID != 0);
 List<EventViewModel> model = events.Select(event => new EventViewModel(){
 Id = event.Id,
 Property1 = event.Property1,
 Property1 = event.Property2
}).ToList();
 return Json(new{ data = model }, JsonRequestBehavior.AllowGet);
}

এটি প্রশ্নের উত্তর দেয় না
ডেন আই

-1

এই সমস্যাটি সমাধানের একটি সহজ বিকল্প একটি স্ট্রিং ফিরে আসা, এবং সেই স্ট্রিংটিকে জাভাস্ক্রিপ্টসিরাইজারের সাহায্যে জসনতে ফর্ম্যাট করা।

public string GetEntityInJson()
{
   JavaScriptSerializer j = new JavaScriptSerializer();
   var entityList = dataContext.Entitites.Select(x => new { ID = x.ID, AnotherAttribute = x.AnotherAttribute });
   return j.Serialize(entityList );
}

এটি "নির্বাচন করুন" অংশটি গুরুত্বপূর্ণ, যা আপনার দৃষ্টিতে আপনি যে বৈশিষ্ট্যগুলি চান তা চয়ন করে। কিছু বস্তুর পিতামাতার জন্য একটি রেফারেন্স থাকে। আপনি যদি বৈশিষ্ট্যগুলি না বাছাই করেন তবে আপনি কেবল সারণীগুলি পুরোপুরি গ্রহণ করলে বিজ্ঞপ্তি উল্লেখটি উপস্থিত হতে পারে।

এটা করো না:

public string GetEntityInJson()
{
   JavaScriptSerializer j = new JavaScriptSerializer();
   var entityList = dataContext.Entitites.toList();
   return j.Serialize(entityList );
}

আপনি যদি পুরো টেবিলটি না চান তবে পরিবর্তে এটি করুন:

public string GetEntityInJson()
{
   JavaScriptSerializer j = new JavaScriptSerializer();
   var entityList = dataContext.Entitites.Select(x => new { ID = x.ID, AnotherAttribute = x.AnotherAttribute });
   return j.Serialize(entityList );
}

এটি কেবলমাত্র আপনার প্রয়োজনীয় বৈশিষ্ট্যগুলির সাথে কম ডেটা দিয়ে একটি ভিউ রেন্ডার করতে সহায়তা করে এবং আপনার ওয়েবকে দ্রুত চালিত করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.