Json.net; сериализовать объект каркаса сущности (круговая ошибка ссылки)

У меня есть сущность framework entity, которую я хочу сериализовать как объект json. Я осмотрелся и узнал, что json.net(http://james.newtonking.com/projects/json-net.aspx) должен иметь возможность сериализовать объекты с круглыми ссылками "из коробки". Поэтому я попытался использовать

string json = JsonConvert.SerializeObject(/* my ef entity */);

Но я все равно получаю ту же ошибку. Проблема может заключаться в том, что мне нужно использовать ReferenceLoopHandling.Ignore и ContractResolver, но я не уверен, как их использовать. Любая помощь высоко ценится! Благодаря

Ответ 1

Моим решением было просто удалить родительскую ссылку на дочерние объекты.

Итак, в моей модели я выбрал связь и изменил ссылку "Родитель" как "Внутренний", а не "Публичный".

Не может быть идеальным решением для всех, но работал у меня.

Ответ 2

Чтобы обойти это, я преобразовал свои сущности в первый код POCO. Для этого щелкните правой кнопкой мыши внутри окна edmx и выберите:

Добавить элемент генерации кодa > вкладка "Код" > EF POCO Entity Generator.

Обратите внимание, что вам может потребоваться установить его с помощью nuget, если вы его не видите.

Однако во время выполнения EF добавляет прокси-классы к этим объектам для целей отслеживания, но они, как правило, испортили процесс сериализации. Чтобы предотвратить это, мы можем просто установить ProxyCreationEnabled в false следующим образом:

var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;

var results = context.YourEntity.Take(100).ToList();

Затем вы можете безопасно возвращать сериализованные данные JSON.NET, опустив цикл ссылок по умолчанию следующим образом:

return JsonConvert.SerializeObject(results, Formatting.Indented, 
    new JsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    });

Ответ 3

Другим решением будет добавление атрибута [JsonIgnore] к вашим навигационным свойствам.

Например:

using System;
using System.ComponentModel.DataAnnotations.Schema;

[Serializable]
public class Entity
{
    public int EntityID { get; set; }
    public string EntityName { get; set; }

    [JsonIgnore]
    public virtual Parent Parent { get; set; }
    [JsonIgnore]
    public virtual List<Child> Children { get; set; }
}

Ответ 4

Я использовал следующее решение для клонирования моих сущностей, никаких трюков, где это необходимо в отношении атрибутов данных для объектов, и мои циклические ссылки в таблице сохранялись. У меня даже были сущности, указывающие друг на друга без каких-либо проблем. Необходимая библиотека для serializaton - Json.Net(DLL Newtonsoft.Json).

    private static T CloneObject<T>(T obj)
    {
        if (obj == null)
            return obj;
        string ser = JsonConvert.SerializeObject(obj, Formatting.Indented, 
            new JsonSerializerSettings() {
                                NullValueHandling = NullValueHandling.Ignore,
                                MissingMemberHandling = MissingMemberHandling.Ignore,
                                ReferenceLoopHandling = ReferenceLoopHandling.Ignore});
        return (T) JsonConvert.DeserializeObject(ser, obj.GetType());
    }

Пример использования:

    protected object CopyObj(Object obj)
    {
        return CloneObject(obj);
    }
    var cust1 = this.cts.Customers().Where(cc => cc.Id == 3).Include(cc => cc.Addresses).FirstOrDefault();
    var cust2 = CopyObj(cust1) as Customers;  
    //Cust2 now includes copies of the customer record and its addresses

Ответ 5

Попробуйте следующее: сначала убедитесь, что poco или модель имеет DataContract, DataMemeber и удаляет виртуальное ключевое слово.. далее..

 public string Get()
    {
        var list = _languageRepository.GetMany(l => l.LanguageTrans.FirstOrDefault().CultureCode == "en").ToList();

        string json = JsonConvert.SerializeObject(list, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });

        return json;
    }