Şu an 2 gün boyunca bunun cevabını arıyorum. Tam olarak neyin yanlış olduğundan emin değilim, ama sanırım olası suçluyu bulmuş olabilirim.Veritabanı Doğrulama Hataları. Tek bir tabloda null değerine izin ver ancak ilgili (normalize edilmiş) tabloya girme
Programım, şirketimde ekipmanı takip edebilecek bir veritabanı izleyici/yöneticisidir. Kullanıcı ekipmanı sorgulayabilir, oluşturabilir ve düzenleyebilir. Şu anda, veritabanı çalışmasını sorguluyor, ancak veritabanına eklemek ya da güncellemeyi denediğimde, program Doğrulama hatalarını atar (bunu daha aşağıya alacağım).
Çok sayıda geçersiz özelliği olan bir donanım sınıfım var (çünkü kullanıcı yeni bir giriş oluştururken bu özelliklerin çoğunu bilmeyebilir, neredeyse tüm nitelikleri geçersiz kılınmış) ve bağlı (yabancı anahtarlar ve tembel yükleme kullanarak)/"sanal") veritabanını normalleştirmeye yardımcı olmak için yapılmış birkaç tabloya. İşte
bazı Kısaltılmış kod yardımcı olmaktır:Ekipman Modeli:
public class Equipment
{
public int EquipmentId { get; set; } //required
public string Company { get; set; } //required
public bool Verified { get; set; } //required
(...other non-required attributes...)
//The following two attributes are where my problems are I believe
[ForeignKey("PAU")]
public int PAUId { get; set; } //required and Foreign Key
//This is not required (but is FK to the related table) if the user doesn't know
[ForeignKey("Division")]
public Nullable<int> DivisionId { get; set; }
//These are the lazy loading connections to the other tables in the database
public virtual Division Division { get; set; }
public virtual PAU PAU { get; set; }
}
Bölümü Modeli: Bu tablo sadece bizim şirkette 5 farklı bölümler ve ilgili Kimliği içeriyor.
public class Division
{
public Division()
{
this.Equipments = new HashSet<Equipment>();
}
//These are non-nullable/required fields
public int DivisionId { get; set; }
public string DivisionName { get; set; }
public virtual ICollection<Equipment> Equipments { get; set; }
}
PAU Modeli: Bu model PAÜ # s ve ilgili açıklama ve kimliği içerir.
public class PAU
{
public PAU()
{
this.Equipments = new HashSet<Equipment>();
}
//These are non-nullable/required fields
public int PAUId { get; set; }
public string PAUNumber { get; set; }
public string PAUDescription { get; set; }
public virtual ICollection<Equipment> Equipments { get; set; }
}
Ekipmanları Denetleyici: Ben veritabanında zaten mümkün seçenekleri ile doldurulur ve bu özelliklere yönelik (yukarıda ViewData içinde saklanan) o açılır listeler var görünümlerinde
public class EquipmentController : Controller
{
TLCP_DEVEntities4 db = new TLCP_DEVEntities4();
(...)
public ActionResult Edit(int id)
{
ViewData["divisions"] = new SelectList(db.Equipments.
OrderBy(x => x.Division.DivisionName).
Select(x => x.Division).ToList().
Distinct(), "DivisionId", "DivisionName");
ViewData["PAUNumbers"] = new SelectList(db.Equipments.
OrderBy(x => x.PAU.PAUNumber).
Select(x => x.PAU).ToList().
Distinct(), "PAUId", "PAUNumber");
return View(db.Equipments.Find(id));
}
[HttpPost]
public ActionResult Edit(Equipment equipment)
{
if (ModelState.IsValid)
{
db.Entry(equipment).State = EntityState.Modified;
db.SaveChanges(); //fails here
return RedirectToAction("Maintenance");
}
ViewData["divisions"] = new SelectList(db.Equipments.
OrderBy(x => x.Division.DivisionName).
Select(x => x.Division).ToList().
Distinct(), "DivisionId", "DivisionName");
ViewData["PAUNumbers"] = new SelectList(db.Equipments.
OrderBy(x => x.PAU.PAUNumber).
Select(x => x.PAU).ToList().
Distinct(), "PAUId", "PAUNumber");
return View(equipment);
}
public ActionResult AddEquipment()
{
ViewData["divisions"] = new SelectList(db.Equipments.
OrderBy(x => x.Division.DivisionName).
Select(x => x.Division).ToList().
Distinct(), "DivisionId", "DivisionName");
ViewData["PAUNumbers"] = new SelectList(db.Equipments.
OrderBy(x => x.PAU.PAUNumber).
Select(x => x.PAU).ToList().
Distinct(), "PAUId", "PAUNumber");
return View();
}
public ActionResult AddEquipment(Equipment equipment)
{
try
{
db.Equipments.Add(equipment);
db.SaveChanges();
return RedirectToAction("Maintenance");
}
catch (Exception ex)
{
ViewData["divisions"] = new SelectList(db.Equipments.
OrderBy(x => x.Division.DivisionName).
Select(x => x.Division).ToList().
Distinct(), "DivisionId", "DivisionName");
ViewData["PAUNumbers"] = new SelectList(db.Equipments.
OrderBy(x => x.PAU.PAUNumber).
Select(x => x.PAU).ToList().
Distinct(), "PAUId", "PAUNumber");
return View();
}
}
(...)
}
. Benim modeli içine bu verileri depolamak birkaç farklı yollar denedi, ancak bu şekilde iyi iş gibi görünüyor: bir sürü hata ayıklama sonra çok
<%: Html.DropDownListFor(model => model.DivisionId,
ViewData["divisions"] as SelectList, "")%>
Tamam, sorun tembel yüklenen özellikler var çünkü görünüyor tablolarında izin verilmeyen boş öznitelikleri. Örneklerim, yeni ekipman nesneleri oluştururken daha fazla uğraşacak, ancak sorunun onları düzenlemek için aynı olduğuna inanıyorum.
Division Örnek: Bu nedenle, Donanım sınıfındaki DivisionId (kullanıcı tanımadığı veya ekipmanın belirli bir bölüme ait olmadığı) boş olabilir ve Ekipman tablosu/sınıfı bu konuda şikayette bulunmaz. Ancak SaveChanges() 'ı denediğimde, programın sanal Division nesnesi null olduğundan şikayetçi olur (varsayılan DivisionId 0 ve boş bir DivisionName vardır). Equipment.DivisionId boş olduğundan, bu Donanım nesnesi için Bölüm tablosunu güncellemek istemiyorum. Bunu aşmanın bir yolu var mı? Tembel yükleme yapmamalı mıyım?
PAU Örnek: PAUId yana tüm aletler nesnelerle için gerekli bir özellik değildir, fakat Bölüm Örnek l'deki gibi, PAU.PAUNumber ve PAU.PAUDescription boş (ve PAU.PAUId varsayılan 0) bir hata neden olur. Bu sadece birincisi gibidir, ancak gerekli nitelikte (farklı şekilde ele alınması gerektiğinden emin değilim).
Bu sorunun nasıl giderileceğinden emin değilim.geç yükleme Kimliği/Yabancı anahtar boş değilse ben sadece bu diğer tablolara benim Ekipmanları nesneyi bağlamak istiyorum çünkü konu
mi?
Donanım nesnesinin değerlerini Kimlikler'e göre diğer tablolardan güncelleyebilecek arayabileceğiniz bir yöntem var mı? Kendimi yaratmam gereken bir yöntem mi?
Tembel yükleme işleminden kurtulursam, sorgularımı nasıl yazmam gerektiğini açıklayabilir misiniz, böylece normalleştirilmiş verilere (DivisionName gibi) hala erişebilir miyim?
Süper uzun yazı için özür dilerim. Önemli olabilecek hiçbir şeyi kaçırmak istemedim.
Düzenleme ben PAU Örnek kaba bir çözüme sahip (ama çünkü Aletindeki boş değerlere fakat şahıs tabloları izin Bölümü Örneği için çalıştığını sanmıyorum).
public ActionResult AddEquipment(Equipment equipment)
{
try
{
equipment.PAU.PAUId = equipment.PAUId;
equipment.PAU.PAUNumber = db.PAUs.Find(equipment.PAUId).PAUNumber;
equipment.PAU.PAUDescription = db.PAUs.Find(equipment.PAUId).PAUDescription;
(...)
}
olsa çok şık değil. Yansımayla ilgili bir öğretiye bakmayı denedim, ama gerçekten anlamlı değildi. Eğer bu daha zarif bir çözüm olurdu, birisi bunu açıklamaya çalışabilir mi?
Hala Bölüm için bir çözüm arıyorum (Equipment.DivisionId öğesinin null olmasına rağmen Division.DivisionId bu işe yaramazsa null değil), ya bu ya da daha zarif bir çözüm için herhangi bir yardım Yukarıdaki büyük takdir edilecektir!
Ve aldığım hata şu ki (çok yararlı değil ve üzerinde aradığımda, bunu düzeltmiş bir yanıt bulamadım): {System.Data.Entity.Validation.DbEntityValidationException: Doğrulama, bir veya daha fazla varlık Daha fazla bilgi için 'EntityValidationErrors' özelliğine bakın. DLMP_Asset_Tracking.Controllers.EquipmentController de System.Data.Entity.Internal.InternalContext.SaveChanges() System.Data.Entity.DbContext.SaveChanges de System.Data.Entity.Internal.LazyInternalContext.SaveChanges() de () de .AddEquipment (Ekipman ekipmanı) –
EntityValidationErrors özelliği ne idi? –
Bu, PAUId = 0 (varsayılan, sağ?) Ve PAUDescription ve PAUNumber öğelerinin null olduğunu gösterir (Bölünme ve yedeklemeden dolayı sorulan soru dışında bıraktığım diğer 4 özellik ile aynıdır). ValidationErrors dizisi, null özelliklerinin (PAUNumber ve PAUDescription) gerekli olduğunu gösterir; bunlar, veritabanı tablolarının ayarlandığı şekilde olur. Bu sorunun cevabını George mu? –