JSON ve Entity ile Genel Bakış sorunu nasıl giderilir


13

Ben sunum katmanı için JSON ve veri modeli / veritabanı için Entity framework ile MVC kaldıraç bir web sitesi oluşturma deniyor. Benim Sorunum Model nesneleri JSON içine serileştirme ile devreye girer.

Veritabanımı oluşturmak için kod ilk yöntemini kullanıyorum. İlk kodu yaparken, bire çok ilişkisine (ebeveyn / çocuk) çocuğun ebeveynine geri başvurması gerekir. (Örnek kod benim bir yazım hatası olmak ama resmi almak)

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;}
 }

Bir "üst" nesneyi JsonResult aracılığıyla döndürürken, "child" sınıf üst özelliğine sahip olduğundan dairesel bir başvuru hatası atılır.

ScriptIgnore özniteliğini denedim ancak alt nesnelere bakma yeteneğini kaybettim. Bilgileri bir noktada ana çocuk görünümünde göstermem gerekecek.

Dairesel referansı olmayan hem ebeveyn hem de çocuk için temel sınıflar yapmaya çalıştım. Ne yazık ki baseParent ve baseChild göndermeye çalıştığımda bunlar türetilmiş sınıfları olarak JSON Parser tarafından okunur (bu kavram beni kaçıyor eminim).

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

Geldiğim tek çözüm "Görünüm" Modelleri oluşturmak. Üst sınıfa başvuru içermeyen veritabanı modellerinin basit sürümlerini oluşturuyorum. Bu görünüm modellerinin her birinde Veritabanı Sürümü'nü ve veritabanı modelini parametre olarak alan bir yapıcı (viewmodel.name = databasemodel.name) döndürme yöntemi vardır. Bu yöntem, çalışmasına rağmen zorunlu görünüyor.

NOT: Buraya gönderiyorum çünkü bunun daha fazla tartışmaya değer olduğunu düşünüyorum. Bu sorunu aşmak için farklı bir tasarım deseni kullanabilirim veya modelimde farklı bir özellik kullanmak kadar basit olabilir. Aramamda bu sorunun üstesinden gelmek için iyi bir yöntem görmedim.

Son hedefim, sunucuyla iletişim kurmak ve verileri görüntülemek için JSON'dan büyük oranda yararlanan güzel bir MVC uygulamasına sahip olmaktı. Katmanlar arasında tutarlı bir model korurken (veya gelebildiğim kadar iyi).

Yanıtlar:


6

Sorunuzda iki ayrı konu görüyorum:

  • JSON'a serileştirirken dairesel referanslar nasıl yönetilir?
  • Görüşlerinizde EF varlıklarını model varlıklar olarak kullanmak ne kadar güvenli?

Dairesel referanslarla ilgili olarak, basit bir çözüm olmadığını söylediğim için üzgünüm. İlk olarak JSON döngüsel başvuruları temsil etmek için kullanılamadığından, aşağıdaki kod:

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

Sonuçlar: TypeError: Converting circular structure to JSON

Tek seçeneğiniz, bileşimin yalnızca kompozit -> bileşen bölümünü tutmak ve "geri gezinme" bileşenini -> kompoziti atmaktır, böylece size örnekte:

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;}
}

Hiçbir şey, burada jQuery kullanarak istemci tarafında bu gezinme özelliğini yeniden oluşturmanızı engellemez:

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

Ancak daha sonra sunucuya geri göndermeden önce tekrar atmanız gerekir, çünkü JSON.stringify dairesel referansı serileştiremez:

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

Şimdi EF varlıklarını görünüm modeli varlıkları olarak kullanma sorunu var.

İlk olarak EF, değişim algılama veya tembel yükleme gibi davranışları uygulamak için sınıfınızın Dinamik Proxy'lerini kullanması muhtemeldir, EF varlıklarını serileştirmek istiyorsanız bunları devre dışı bırakmanız gerekir.

Ayrıca, tüm varsayılan ciltleyici, kullanıcının ayarlamasını istemediğinizler de dahil olmak üzere istekten varlık alanlarıyla her alanı eşleştireceğinden, kullanıcı arabiriminde EF varlıklarını kullanmak risk altında olabilir.

Böylece, MVC app düzgün tasarlanmış olmasını istiyorsanız ben iç iş modeli "cesaret" müşteriye maruz kalmasını önlemek için özel bir görünüm modeli kullanmanızı tavsiye ederim, böylece size belirli bir görünüm modeli tavsiye ederim.


Dairesel referans ve EF sorunu etrafında alabilirsiniz nesne odaklı teknikler ile süslü bir yolu var mı.
DanScan

Hem dairesel referansı hem de EF sorununu çözebileceğim nesne yönelimli tekniklerle süslü bir yol var mı? BaseObject gibi entityObject ve viewObject tarafından miras alınır. Böylece entityObject dairesel referansa sahip olurken viewObject dairesel referansa sahip olmaz. EntityObject (viewObject.name = entityObject.name) viewObject yapılandırarak bu etrafında aldık ama bu zaman kaybı gibi görünüyor. Bu sorunu nasıl çözebilirim?
Mart'ta DanScan

Onlar seni çok . Açıklamanız çok net ve anlaşılması kolaydı.
Nick

2

Nesneleri serileştirmeye çalışmanın daha basit bir alternatifi, üst / alt nesnelerin serileştirilmesini devre dışı bırakmak olacaktır. Bunun yerine, ilişkili üst / alt nesneleri ihtiyacınız olduğunda ve gerektiğinde getirmek için ayrı bir çağrı yapabilirsiniz. Bu, uygulamanız için ideal olmayabilir, ancak bir seçenektir.

Bunu yapmak için bir DataContractSerializer kurabilir ve DataContractSerializer.PreserveObjectReferences özelliğini veri modeli sınıfınızın yapıcısında 'false' olarak ayarlayabilirsiniz . Bu, HTTP yanıtlarının serileştirilmesinde nesne başvurularının korunmaması gerektiğini belirtir.

Örnekler:

Json biçimi:

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

XML biçimi:

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

Bu, başvurulan alt nesneleri olan bir öğeyi alırsanız, alt nesnelerin serileştirilmeyeceği anlamına gelir.

Ayrıca bkz. DataContractsSerializer sınıfı.


1

Dairesel Referanslarla ilgilenen JSON serileştiricisi

JSONSerializerİlk örneği serileştirerek ve referencesonraki tüm durumlarda bir * ilk örneğe kaydederek dairesel referanslarla ilgilenen bir özel Jackson örneği.

Jackson ile nesneleri seri hale getirirken Dairesel Referanslarla başa çıkmak

Yukarıdaki makaleden ilgili kısmi snippet:

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

Geldiğim tek çözüm "Görünüm" Modelleri oluşturmak. Üst sınıfa başvuru içermeyen veritabanı modellerinin basit sürümlerini oluşturuyorum. Bu görünüm modellerinin her birinde Veritabanı Sürümü'nü ve veritabanı modelini parametre olarak alan bir yapıcı (viewmodel.name = databasemodel.name) döndürme yöntemi vardır. Bu yöntem, çalışmasına rağmen zorunlu görünüyor.

Minimum veriyi göndermek tek doğru cevaptır. Veritabanından veri gönderdiğinizde, her bir sütunu tüm ilişkilendirmelerle göndermek genellikle mantıklı değildir. Tüketicilerin veritabanı ilişkilendirmeleri ve yapılarıyla, yani veritabanları ile uğraşmaları gerekmemelidir. Bu sadece bant genişliğini korumakla kalmaz, aynı zamanda bakımı, okunması ve tüketilmesi de çok daha kolaydır. Verileri sorgulayın ve sonra eq göndermek için gerçekten ihtiyacınız olan şeyleri modelleyin. çıplak asgari.


Büyük verilerden bahsederken daha fazla işlem süresi gerekiyor, çünkü şimdi her şeyi iki kez dönüştürmeniz gerekiyor.
David van Dugteren

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.