我正在尝试在LINQ to SQL个实体的基类中实现验证框架。我遇到的问题是让OnValidate事件正常启动。
原因是OnValidate被标记为partial,所以我不能在基类中提供默认实现;它被LINQ to SQL类声明的新方法隐藏。
如何修复它以便自动调用基类中的OnValidate事件?
示例代码如下。
public class EntityBase
{
public bool IsValid
{
get { return (GetValidationErrors().Count() == 0); }
}
public virtual IEnumerable<ValidationError> GetValidationErrors()
{
yield break;
}
public void OnValidate(System.Data.Linq.ChangeAction action)
{
//This never gets fired unless I call explicitly in the derived class.
if (!IsValid)
{
StringBuilder sb= new StringBuilder();
sb.AppendLine("Validation errors prevent saving");
foreach (ValidationError error in GetValidationErrors())
{
sb.AppendLine(String.Format("{0}: {1}", error.PropertyName, error.ErrorMessage));
}
throw new ApplicationException(sb.ToString());
}
}
}
public partial class LinqThingy: EntityBase
{
public override IEnumerable<ValidationError> GetValidationErrors()
{
if (String.IsNullOrEmpty(Name)) yield return new ValidationError("Name required", "Name");
}
//Eww nasty, don't want to have to do this.
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
base.OnValidate(action);
}
}
答案 0 :(得分:2)
您可以覆盖DataContext类中的SubmitChanges(ConflictMode)方法。这将确保所有实体在持久化之前得到验证。这样您就不必为实体创建自定义基类。以下是如何扩展DataContext类的示例:
public partial class NorthwindDataContext
{
public override void SubmitChanges(ConflictMode failureMode)
{
EntityValidator.Validate(this.GetChangedEntities());
base.SubmitChanges(failureMode);
}
private IEnumerable<object> GetChangedEntities()
{
ChangeSet changes = this.GetChangeSet();
return changes.Inserts.Concat(changes.Updates);
}
}
在上面的示例中,自定义验证逻辑进入EntityValidator类中的Validate方法(当然,您必须创建它)。
This article展示了如何使用O / RM技术验证实体,例如LINQ to SQL。虽然它使用企业库验证应用程序块,但该文章可能适用于您的情况。
答案 1 :(得分:0)
如果您正在寻找要继承的BaseDataContext,我的示例如下:
public class BaseDataContext : DataContext
{
// constructor is needed if you have different contexts
public BaseDataContext(string fileOrServerOrConnection) : base(fileOrServerOrConnection)
{
}
public override void SubmitChanges(ConflictMode failureMode)
{
try
{
base.SubmitChanges(failureMode);
}
catch (Exception ex)
{
// do whatever you would like with the exception
}
}
}