.net - EF SaveChanges 不调用 Validate (IValidatableObject)

标签 .net entity-framework c#-4.0

默认情况下,EF 在生成对象时使用 EntityObject。我已将其修改为使用我自己的 AbstractEntityObject 类。在此过程中,我添加了 IValidatableObject,因为当您调用 context.SaveChanges() 时,我的印象是它会自动调用 Validate 并抛出异常。

这是我所拥有的:

public abstract class AbstractEntityObject : EntityObject, IValidatableObject
{
    private readonly DBTable table;

    protected AbstractEntityObject(DBTable table)
    {
        this.table = table;
    }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        List<OITValidationResult> results = new List<OITValidationResult>();
        List<PropertyInfo> properties = new List<PropertyInfo>(GetType().GetProperties());

        foreach (DBField field in table.GetFields())
        {
            foreach (PropertyInfo prop in properties)
                if (StringUtilities.EqualsIgnoreCase(field.FieldName, prop.Name))
                {
                    results.AddRange(field.Validate(prop.GetValue(this, null)));
                    results.AddRange(AdditionalValidation(field, prop));
                    properties.Remove(prop);
                    break;
                }
        }

        return results;
    }

    public abstract List<OITValidationResult> AdditionalValidation(DBField field, PropertyInfo prop);
}

public abstract class AbstractTLMSEntityObject : AbstractEntityObject
{
    protected AbstractTLMSEntityObject(DBTable table) 
        : base(table)
    {
    }

    public override List<OITValidationResult> AdditionalValidation(DBField field, PropertyInfo prop)
    {
        List<OITValidationResult> results = new List<OITValidationResult>();

        if (!EntityState.Equals(EntityState.Unchanged))
        {
            if (StringUtilities.EqualsIgnoreCase(field.FieldName, "userid"))
                prop.SetValue(this, TLMSDB.User.UserName, null);
            else if (StringUtilities.EqualsIgnoreCase(prop.Name, "dtmod"))
                prop.SetValue(this, DateTime.Now, null);
        }

        OITValidationResult additionalResult = AdditionalValidation(field.Field);
        if (additionalResult != null)
            results.Add(additionalResult);

        return results;
    }

    /* By default there is no additional validation, subclasses should override this if they need additional validation */
    public virtual OITValidationResult AdditionalValidation(Enum field)
    {
        return null;
    }
}

然后,我有了子类,它是 EF 创建的部分类:

public partial class CSDCrud
{
    public enum Fields
    {
        RECEIPT_NUMBER,
        GRANT_ID,
        GRANT_FUND,
        TOTAL_ACRES
    }

    public CSDCrud() : base(CSDCrudDAO.Instance.Table)
    {
    }

    public static String GetDataPropertyName(Enum field)
    {
        return CSDCrudDAO.Instance.Table.GetField(field).FieldName;
    }
}

由于我在 .tt 文件中进行了更改,CSDCrud 继承自 AbstractTLMSEntityObject。

现在事情变得奇怪了。我已经设置了它,以便 DBField(在父类中引用)对数据进行 self 验证。在这种情况下,我已经将其设置为如果需要receipt_number,则会失败并抛出异常...事实上,会发生以下情况...

List<OITValidationResult> results = (List<OITValidationResult>)crudObject.Validate(null);
try
{
    CommonEntityManager.GetContext().CrudSet.AddObject(crudObject);
    CommonEntityManager.GetContext().SaveChanges();
    return true;
}
catch (Exception ex)
{
    return false;
}

正如预期的那样,结果包含 1 个项目,这是正确的错误...但是 SaveChanges 将其保存得很好,没有抛出异常...我错过了什么?

编辑:我应该注意,显然我可以使用 SavingChanges 事件添加我自己的处理程序,但我希望使用预先存在的基础设施。

static void context_SavingChanges(object sender, EventArgs e)
    {
        foreach (ObjectStateEntry ose in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
        {
            List<ValidationResult> results = new List<ValidationResult>(((IValidatableObject)ose.Entity).Validate(null));
            if (results.Count > 0)
                throw new CustomException(results);
        }

        foreach (ObjectStateEntry ose in context.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
        {
            List<ValidationResult> results = new List<ValidationResult>(((IValidatableObject)ose.Entity).Validate(null));
            if (results.Count > 0)
                throw new CustomException(results);
        }
    }

最佳答案

仅当您使用 DbContext API 而不是 ObjectContext API 时才会调用内置验证。

关于.net - EF SaveChanges 不调用 Validate (IValidatableObject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13073221/

相关文章:

c# - HttpUtility.HtmlEncode、HttpUtility.HtmlDecode、AntiXSS 库和正确格式化用户输入

c# - Panel.TabStop = true 没有效果

C# web 控件是否会在 visible 为 false 时显示

C# Transaction Scope 在同一台服务器上有 2 个数据库导致异常

mysql - 无法从 asp.net mvc 项目连接到 MySQL

asp.net - 使用 Web API 的动态路由

.net - Visual Studio 的配置管理器有替代/插件吗?

c# - 如何识别标记为级联删除的关联

c# - 我应该在哪里放置功能以在类型之间进行转换?

c# - 使用 C# 删除目录上的只读属性