DbSet<T>.Local
提供了一个可以绑定到WPF控件的ObservableCollection
。就我而言,我将它绑定到网格。
如果我使用的是视图模型,我会让它们实现INotifyDataErrorInfo
或IDataErrorInfo
,然后编写Fluent Validation验证器来处理验证。
但是在这里我通过DbSet<T>.Local
绑定了模型。我该如何处理验证?
我应该在模型上实施INotifyDataErrorInfo
还是IDataErrorInfo
?
或者有其他选择吗?
答案 0 :(得分:1)
如果您的应用程序是胖客户端,意味着应用程序的所有层都在一台物理机器上,那么您应该在模型上实现IDataErrorInfo
。
另一方面,如果您的应用程序是一个瘦的多累应用程序,意味着您的模型是在服务器上实现的,并且您正在使用WPF桌面应用程序与服务器端代码进行通信,那么您应该实现{{1 }}
答案 1 :(得分:1)
是的,我认为在POCO模型中实现IValidatableObject的实现是有意义的。
您可能已经注意到public ObservableCollection<TEntity> Local { get; }
有几种方法可以做到这一点。所以做了一些功课。
As some background , might be useful
所以我们知道EF有触发验证的概念。
Configuration.ValidateOnSaveEnabled = true;
EF也会拨打IEnumerable<ValidationResult> ValidateInstance();
来自界面IValidatableObject
如果您的实体POCO实施IValidatableObject
EF将在SAve上触发验证。 您还可以在需要时轻松触发验证。
这一切都与UoW概念完全相关。
public IEnumerable<DbEntityValidationResult> GetDbValidationErrors() { return
Context.GetValidationErrors(); } // Standard Context call get the problems
可以使用 catch(Exception ex){.... var x = GetDbValidationErrors(); //....
所以我认为你走在正确的轨道上......
编辑:添加SAMPLE POCOBase并演示触发器验证。
public interface IFBaseObject : IValidatableObject {
// a POCO object must implement the VALIDATE method from IValidatableObject
bool IsValidInstance();
IEnumerable<ValidationResult> ValidateInstance();
}
public abstract class BaseObject : IFBaseObject {
// .... base object stuff removed....
/// <summary>
/// Get called every a Validation is trigger on an object. Here we return and Empty resultset to start with.
/// If you override ALWAYS call Base first and Continue to add your own results as desired.
/// Never fail to call base First !
/// </summary>
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
# region Sample implementation for a POCO thats needs validation
/* Sample Implementation a sub type POCO might use.
var validationResult = base.Validate(validationContext).ToList();
if (true) // the condition that leads to a validation error
{
var memberList = new List<string> { "PropertyName" }; // the name of the offending property
var error = new ValidationResult("Error text goes here", memberList); // use teh textpool !!! no hardcoded texts
validationResult.Add(error);
}
return validationResult;
*/
# endregion
// now back in the base Class.
var validationResult = new List<ValidationResult>();
// hand back a list that is empty so errors if any can be added by SUBclasses
// we can check any Poco that implements a certain interface centrally.
var thisIsKeyGuid = this as IFKeyGuid;
if (thisIsKeyGuid != null) {
if (thisIsKeyGuid.Id == Guid.Empty) {
validationResult.Add(new ValidationResult("Id is required", new List<string>() {"Id"}));
}
}
return validationResult;
}
/// <summary>
/// Allows explicit triggering of Validation and returns a TRUE or false answer. Call anytime
/// </summary>
/// <returns></returns>
public virtual bool IsValidInstance() {
List<ValidationResult> vResults;
return SelfValidation(out vResults);
}
/// <summary>
/// Calls Self Validation which uses THIS object as the context for validation.
/// This means you can trigger a validation without first declaring a validation context.
/// IValidatableObject is effectively called for you. Witch causes "Validate" to be called
/// </summary>
/// <returns></returns>
public IEnumerable<ValidationResult> ValidateInstance() {
List<ValidationResult> vResults;
SelfValidation(out vResults);
return vResults;
}
/// <summary>
/// Although SelfValidation is defined at BaseObject level, this triggers the VALIDATION process on the current Object
/// see http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validator.aspx for mroe details
/// So if a POCO Object has overridden public virtual IEnumerable of ValidationResult Validate(ValidationContext validationContext)
/// then this method will be called. It should of course call :base.Validate
/// </summary>
/// <returns>true or false</returns>
private bool SelfValidation(out List<ValidationResult> vResults) {
var vc = new ValidationContext(this, null, null);
vResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(this, vc, vResults, true);
return isValid;
}
}