Как определить саморегулирующуюся l oop? - PullRequest
0 голосов
/ 28 мая 2020

У меня есть модель ниже от объекта EF:

public partial class Commodity
{
    public Commodity()
    {
        this.CommodityVarieties = new HashSet<CommodityVariety>();
    }

    public int CommodityID { get; set; }
    public string CommodityName { get; set; }
    public string CommodityVarietyDisplayName { get; set; }
    public string BackColor { get; set; }
    public string ForeColor { get; set; }
    public bool IsDeleted { get; set; }
    public int SortOrder { get; set; }

    public virtual ICollection<CommodityVariety> CommodityVarieties { get; set; }

}

public partial class CommodityVariety
{
    public int VarietyID { get; set; }
    public int CommodityID { get; set; }
    public string VarietyName { get; set; }
    public bool IsDeleted { get; set; }

    public virtual Commodity Commodity { get; set; }
}

Я хотел бы получить список товаров и преобразовать этот список в строку JSON, используя Newtonsoft. Следовательно, я пишу

DbContext context = new DbContext();
var list = context.Commodities.ToList();
string json = JsonConvert.SerializeObject(list);

Я получаю ошибку ниже:

Самостоятельная ссылка l oop обнаружена для свойства 'Commodity' с типом 'System.Data.Entity.DynamicProxies .Commodity_B55D25F995ED72E0B75FED715153713965D91EB5A3BF576322FE6DEAC130C0F5 '. Путь '[0] .CommodityVariety [0]

Я знаю, что это из-за ссылки на Commodity в классе CommodityVariety.

Чтобы избежать, я обновил JSON Параметр сериализации должен иметь от ReferenceLoopHandling до Ignore, как показано ниже:

options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

Вышеуказанные настройки дают мне

Было выбрано исключение типа 'System.OutOfMemoryException'.

Я перепробовал все возможные ответы из StackOverflow.

Наконец, сделал

public DbContext() : base("name=DbContextEntity")
{
    Configuration.LazyLoadingEnabled = false;
    Configuration.ProxyCreationEnabled = false;
}

Теперь код работает без ошибок и Commodity.CommodityVarieties имеет значение null.

У меня так много внешних ключей, и очень сложно сопоставить их все вручную после установки ProxyCreationEnabled на false.

Есть ли способ идентифицировать себя ссылаться до JSON сериализации и сделать его нулевым? Как показано ниже:

DbContext context = new DbContext();
var list = context.Commodities.ToList();

//filter only properties of `Commodity` property and find object of type `Commodity`
//var suspectObjects = list.Any(x => x.OfType<Commodity>()).ToList();
//suspectObjects.ForEach(item => { item = null; });

//I know the above segment will not work. I seek your help and I thought something like above explain more to you what I want actually.

string json = JsonConvert.SerializeObject(list);

1 Ответ

0 голосов
/ 28 мая 2020

Ну ... в основном, чаще всего модель базы данных не подходит для сериализации в JSON. Вот почему часто существует слой сопоставления, который транслирует структуры из БД в структуры API. EF, NH, XPO, что угодно) отслеживает изменения, теперь вы получаете рискованную ситуацию: что, если кто-то / что-то зафиксирует изменения впоследствии? Вы сохраните много NULL в БД и сломаете свои данные. решить, что делать, если в сериализованном графе объекта обнаружена циклическая ссылка. Проверьте документацию.

Например, если вы используете Newtonsoft, попробуйте ReferenceLoopHandling

Вы также можете использовать атрибуты или настройки, чтобы сериализатор игнорировал определенные свойства. В приведенном вами примере исключение CommodityVariety.Commodity нарушит ссылку l oop и также решит проблему. Родительский класс имеет набор детей, дети больше не заботятся о родителе, все в порядке для JSON. Однако после десериализации вам может потребоваться вручную исправить обратные ссылки между дочерними и родительскими элементами.

Вы также можете реализовать и добавить свои собственные плагины для сериализатора и полностью определить сериализацию, как вам нравится, что верное решение, но здесь для этой проблемы явный излишество.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...