기본적으로 EF는 개체를 생성 할 때 EntityObject를 사용합니다. 내 자신의 AbstractEntityObject 클래스를 사용하도록 수정했습니다. 그렇게하면서, IValidatableObject를 추가했습니다. context.SaveChanges()를 호출했을 때 인상적 이었기 때문에 자동으로 Validate를 호출하고 예외를 throw합니다.EF SaveChanges가 호출하지 않음 Validate (IValidatableObject)
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;
}
}
CSDCrud가 AbstractTLMSEntityObject 감사에서 상속을 여기
내가 가진 무엇 나는 .tt 파일에서 그것을 변경했다.여기가 이상해집니다. DBField (부모 클래스에서 참조)가 데이터의 자체 유효성 검사를 수행하도록 설정했습니다. receipt_number가 실패하고 사실, 다음이 발생합니다 ... 예외가 발생합니다 따라서 필요하고이 경우에, 나는 결과 1 개 항목을 포함하는,
List<OITValidationResult> results = (List<OITValidationResult>)crudObject.Validate(null);
try
{
CommonEntityManager.GetContext().CrudSet.AddObject(crudObject);
CommonEntityManager.GetContext().SaveChanges();
return true;
}
catch (Exception ex)
{
return false;
}
이 예상대로 ... 그래서를 설정 한 적절한 오류 ... 그러나 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);
}
}
당신이 ObjectContext를 사용하고 있습니까? 유효성 검사는 DbContext를 사용하는 경우에만 호출됩니다. 죄송합니다. 질문을 다시 읽어야합니다. – Pawel
OK. 다시 읽었습니다. 문제의 수정 코드 인 마지막 코드 조각이 오도되었습니다. 유효성 검사는 DbContext를 사용할 때만 작동합니다. – Pawel
@Pawel 엔티티 프레임 워크가 모델 유효성 검사를 수행하지 않으면 IValidatableObject 인터페이스를 구현하는 엔티티 클래스의 전체 목적은 무엇입니까? 그런 다음 엔터티가 데이터베이스에 커밋되기 전에 누가 호출해야합니까? objectContext에 객체를 추가 할 때마다 내 엔티티 객체의 속성 변경 이벤트에서 List를 만들 수 있습니다. 이 목록은 누군가가 원할 경우 Validate 메소드를 통해 반환 될 수 있습니다. –
RBT