باستخدام MVC و يجيد Nhibernate, كيف يمكنني التحقق من صحة فريدة من نوعها الحقول على ViewModel قبل أن ربط لهم إلى كائن المجال و حفظها ؟
سؤال
لدي موقع على شبكة الانترنت حيث تسمح للمستخدمين إنشاء جزء جديد السجلات.أنا في محاولة لمعرفة أفضل طريقة للتحقق من مجالات محددة من أجل التفرد.أريد أن تأكد من أن شخص ما لا تحاول أن إضافة جزء مع PartNumber 1234 إذا كان هذا PartNumber موجود بالفعل على جزء مختلف.
تطبيق ويب باستخدام Asp.net MVC مع يجيد nHibernate لرسم خرائط بلدي الكائنات في قاعدة البيانات.أنا باستخدام القلعة المصادقة على عرض نماذج لأشياء مثل ValidateNonEmpty, ValidateRange ، إلخ.يجب استخدام ValidateSelf طريقة الاستعلام عن مستودع لمعرفة ما إذا كان رقم الجزء بالفعل ؟ شيء لا يشعر الحق حول استخدام بلدي مستودع على ViewModel.
سيكون من الأفضل بالنسبة لي أن مكان هذا المنطق على وحدة تحكم العمل ؟ هذا لا يبدو صحيحا لأن أتوقع ViewModel أن يكون بالفعل التحقق من صحتها عند النقطة (خلال ModelBind).
أو ربما لا شيء مما سبق.شكرا على أي مساعدة على هذا واحد.
التحديث حسنا, لست متأكدا إذا كان هذا سوف يساعد ، ولكن هنا هو ما حفظ العمل يبدو نموذجية إنشاء العمل في المشروع:
public ActionResult Create(PartViewModel viewModel)
{
//I think I'd like to know if its Valid by this point, not on _repository.Save
if(ModelState.IsValid)
{
try
{
var part = _partCreateViewModelMap.MapToEntity(viewModel);
_repository.Save(part);
return Redirect("~/Part/Details/" + part.Id);
}
catch (Exception e)
{
// skip on down...
}
}
// return view to edit
return View(viewModel);
}
المحلول
لقد سئلت هذا السؤال مرات عديدة.أصدقائي كانوا قلقين حول ما إذا كان يمكن أن تؤدي الوصول إلى البيانات من مدقق رمز.الجواب بسيط.إذا كنت بحاجة إلى القيام بذلك ، يجب أن تفعل ذلك.عادة ما نحتاج إلى القيام به تلك الشيكات في كل مستوى من التجريد.و بعد كل الشيكات يجب أن تكون على استعداد للقبض استثناء ، الناجمة عن انتهاك القيد.
نصائح أخرى
إذا قمت بتعريف فريدة من نوعها القيد في قاعدة البيانات, ثم لماذا لا تفويض المسؤولية إلى التحقق من ما إذا كانت قيمة فريدة من نوعها بالفعل إلى قاعدة البيانات ؟ باستخدام NHibernate ، يمكنك استخدام NHibernate.Exceptions.ISQLExceptionConverter
واجهة لالتقاط وتحويل أخطاء المعروفة المتعلقة القيد الانتهاكات.يمكنك أيضا استخدام NHibernate.Exceptions.IViolatedConstraintNameExtracter
منفذي (انظر NHibernate.Exceptions.TemplatedViolatedConstraintNameExtracter
) للحصول على ضيع تفاصيل قاعدة البيانات الخاصة بك استثناء ، وتحويلها إلى صديقة للمستخدم رسالة حزم مثل التحقق من صحة الاستثناء من تنحاز وقبض عليه في ذات تحكم.
مثال سريع جدا محددة سريعة وقذرة استثناء محول من أحد المشاريع:
Imports NHibernate
Imports NHibernate.Exceptions
Imports System.Data.SqlClient
Imports System.Data.Common
Namespace NHibernate
Public Class ConstraintViolationExceptionConverter
Implements ISQLExceptionConverter
Public Function Convert(ByVal adoExceptionContextInfo As Global.NHibernate.Exceptions.AdoExceptionContextInfo) As System.Exception Implements Global.NHibernate.Exceptions.ISQLExceptionConverter.Convert
Dim dbEx As DbException = ADOExceptionHelper.ExtractDbException(adoExceptionContextInfo.SqlException)
If TypeOf dbEx Is SqlException Then
Dim sqlError As SqlException = DirectCast(dbEx, SqlException)
Select Case sqlError.Number
Case 547
Return New ConstraintViolationException(adoExceptionContextInfo.Message, adoExceptionContextInfo.SqlException)
End Select
End If
Return SQLStateConverter.HandledNonSpecificException(adoExceptionContextInfo.SqlException, adoExceptionContextInfo.Message, adoExceptionContextInfo.Sql)
End Function
End Class
End Namespace
تكوين من خلال web.config/nhibernate-configuration/session-factory
عنصر الملكية:
<property name="sql_exception_converter">csl.NHibernate.ConstraintViolationExceptionConverter, csl</property>
تحرير: ربما ينبغي الإشارة إلى أن تحويل واجهة تغير في الإصدارات الأخيرة من NHibernate ، واجهة من هذا المثال هو من NHibernate.dll v2.1.0.4000
أنا عادة وضع طبقة الخدمة بين وحدات التحكم و مستودعات.
خدمة طبقة ثم التعامل مع التحقق من صحة و يدعو إلى مستودع.
ثم إذا كان هناك خطأ في التحقق من صحة في خدمة طبقة أرمي مخصص استثناء ، قبض عليه في تحكم وحقن أخطاء في نموذج الدولة.
ليس لدي جواب لسؤالك لكن يمكنك التحقق sharparchitecture.net الموقع.أنه يحتوي على بعض أفضل practives على asp.net mvc و nhibernate.كما يمكن أن ننصح للتحقق xval المشروع و الدروس حول التحقق من صحة البيانات مع الشرح المصادقون
لقد وجدت الحل الذي يعمل بالنسبة لي هو
1.) اسأل إذا كان الكيان صالحة لتنفيذ التحقق من صحة العمل.
2.) بعد الانتهاء من ذلك يجب أن يكون شيئا على كائن تبين انها صحيحة أم لا (في حالة استخدام CSLA مثل مفهوم "كسر القواعد").
3.) إذا كان لديك شيء من هذا القبيل يمكنك التحقق من وجوه صحيحة قبل NHibernate يحاول أن تستمر كما هو موضح أدناه.
المشكلة الوحيدة مع هذا النهج هو أن تحتاج إلى تنفيذ واجهة على كل كيان تتطلب التحقق من الصحة.إذا كنت تستطيع العيش مع هذا سوف تتوقف NHibernate من استمرار التغييرات كائن غير صالحة وفقا القواعد الخاصة بك.
using System;
using NHibernate;
using NHibernate.Event;
using Validation.Entities.Interfaces;
using Persistence.SessionBuilder;
namespace Persistence.Validation
{
public class ValidationEventListener : IPreInsertEventListener, IPreUpdateEventListener
{
public bool OnPreInsert(NHibernate.Event.PreInsertEvent @event)
{
var entityToInsert = @event.Entity as IBusinessBase;
if (entityToInsert != null)
{
if (entityToInsert.BrokenRules != null)
{
RollbackTransactionBecauseTheEntityHasBrokenRules();
}
}
return false;
}
public bool OnPreUpdate(NHibernate.Event.PreUpdateEvent @event)
{
var entityToUpdate = @event.Entity as IBusinessBase;
if (entityToUpdate != null)
{
if (entityToUpdate.BrokenRules != null)
{
RollbackTransactionBecauseTheEntityHasBrokenRules();
}
}
return false;
}
private void RollbackTransactionBecauseTheEntityHasBrokenRules()
{
try
{
ISession session = SessionBuilderFactory.GetBuilder().CurrentSession;
if (session != null)
{
session.Transaction.Rollback();
}
}
catch (Exception ex)
{
//this will force a rollback if we don't have a session bound to the current context
throw new NotImplementedException();
}
}
}
}
أود أن أقول هذه المسائل في الهندسة.مع MVC التطبيقات التي كنت قد فعلت في الماضي كنا مجردة بعيدا المجال الاشياء بعيدا عن شبكة الإنترنت الاشياء و بطبيعة الحال نحن نستخدم حقن التبعية لتجنب بجد التبعيات.
عندما يتعلق الأمر إلى التحقق من صحة النموذج عندما كنت في قانون ملزم ، نعم يمكن بسهولة استخدام الخدمة, مستودع, أو أيا كان لديك المقبل في العمارة في ValidateSelf الأسلوب.أعتقد أن السؤال ارتفاع ماذا عن التبعية.
إذا كنت أتذكر بشكل صحيح يمكنك إنشاء الخاص بك مخصص الموثق أن استخدام حقن التبعية إطار المكونات في أي خدمات النموذج الخاص بك يحتاج للمصادقة عند إنشائه ، اتصل MVC الافتراضي الموثق لملء كائن ، ثم الدعوة إلى القلعة التحقق من صحة إطار القيام التحقق من الصحة.هذا ليس فكر بشكل كامل الحل ، ولكن نأمل أن يثير بعض الأفكار.