我知道有一个AssociationChanged事件,但是,这个事件在关联建立后触发。没有AssociationChanging事件。因此,如果出于某种验证的原因,我想抛出一个异常,我如何做到这一点并返回到我的原始值?
此外,我希望根据来自其他实体的信息为我的实体设定默认值,但只有当我知道实体被插入到数据库时才会这样做。我该如何区分它和被实例的对象之间的区别,因为它即将基于现有的数据填充?我应该知道吗?这是在我的实体业务逻辑之外考虑的业务逻辑吗?
如果是这样的话,那么我应该设计控制器类来包装所有这些实体吗?我担心的是,如果我返回一个实体,我希望客户机能够访问这些属性,但是我希望对如何设置、默认等等的验证保持严格的控制。我看到的每个示例都引用上下文,这超出了我的敌意部分类验证的范围,对吗?
顺便说一句,我看了EFPocoAdapter,为了我的生命,我无法决定如何从我的POCO类中填充列表.有人知道我是如何从EFPoco类获得上下文的吗?
发布于 2010-12-23 19:11:45
这是对我留下的一条评论的回应。希望这能回答你的问题,希米。评论一下,如果它不回答你的问题,我会把它缩短或者删除。
您需要在类上实现INotifyPropertyChanging和INotifyPropertyChanged接口(除非它类似于实体框架对象,我认为它是在内部实现的)。
在为该属性设置值之前,需要使用NotifyPropertyChanging.PropertyChanging构造函数中属性的名称引发PropertyChangingEventArgs事件。
设置此值后,需要再次使用在NofityPropertyChanged.PropertyChanged构造函数中引发的属性的名称引发PropertyChangedEventArgs事件。
然后,您必须处理PropertyChanging和PropertyChanged事件。在PropertyChanging事件中,您需要缓存该值。在PropertyChanged事件中,您可以比较并抛出异常。
要从PropertyChanging/PropertyChanged事件args获取属性,您需要使用relf辙。
// PropertyName is the key, and the PropertyValue is the value.
Dictionary <string, object> propertyDict = new Dictionary<object, object>();
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it checks if e.PropertyName already exists.
propertyDict.Add(e.PropertyName, propertyValue);
} // End PropertyChanging() Event
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it makes sure e.PropertyName exists.
object oldValue = propertyDict(e.PropertyName);
object newValue = propertyValue;
// No longer needed.
propertyDict.Remove(e.PropertyName);
if (/* some condition */)
{
try {
preventRecursion = true;
info.SetValue(oldValue, null);
Throw New Exception();
} finally {
preventRecursion = false;
} // End try
} // End if
} // End PropertyChanging() Event
注意我是如何使用PreventRecursion的,这是我忘记在这些方法上面添加的一个布尔值。当您将属性重置回其先前的值时,这些事件将被召回。
tl;dr
现在,您可以派生一个继承自INotifyPropertyChanged的单个事件,但是使用一个参数,该参数包含一个对象,该对象表示前面的值以及属性名。这将将被触发的事件减少到一个,具有类似的功能,并与INotifyPropertyChanged具有向后兼容性。
但是,如果您想在设置属性之前处理任何事情(假设属性进行了不可逆转的更改,或者您需要在设置该变量之前设置其他属性,否则会引发异常),您将无法这样做。
总的来说,这种方法是一种非常古老的做事方式。我会采取扑克维利安的答案,并有无效的数据可以输入。但不允许保存到数据库。
实体框架有一些用于验证的优秀代码。通过属性向属性添加验证。然后负责处理这些属性的工作。然后您可以创建一个名为IsValid的属性,该属性调用实体框架特定的验证。它还区分字段错误(例如输入错误字符或字符串过长)和类错误(例如缺少数据或键冲突)。
然后,您可以将IsValid绑定到控件验证,当输入无效数据时,它们将显示一个红色气泡。或者您可以自己实现IsValid验证。但是,如果IsValid为false,则SaveChanges事件将需要取消保存。
顺便说一下。所提供的代码不会编译,仅为伪代码(混合vb和c#)。但我认为它比c#本身描述性要强得多--准确地显示了正在处理的是什么。
发布于 2009-08-19 17:36:20
关于您的第一个问题,我只是将对关联的更改作为业务逻辑来实现。例如,如果您添加一个具有多个学生的教师类,则不要添加
aTeacher.Students.Add(new Student)
相反,创建一个AddStudent方法
public Student AddNewStudent(string name, string studentID)
{
Student s = new Student( name, studentID);
s.Teacher = this; // changes the association
return s;
}
这样,您就可以完全控制何时更改关联。当然,是什么阻止了另一个程序员直接添加一个学生呢?在学生方面,可以将教师设置为私有(并将构造函数更改为接受教师或类似的构造函数)。在教师方面,如何使学生的收藏不可插入?我不确定..。可能在不接受插入的自定义集合中转换它。
关于问题的第二部分,您可能可以使用OnVarNameChanging事件。如果EntityState是'New‘,那么您可以应用获取实际值的逻辑。
在保存更改时也会触发一个事件(OnSavingChanges?)可以用来确定哪些对象是新的,并设置一些值。
但是,最简单的解决方案可能是始终在构造函数中设置默认值,如果从DB加载数据,它们将被覆盖。
祝好运
发布于 2009-09-23 21:46:10
创建一个工厂,根据需要为您生成实例,如下所示:
getStudent(String studentName, long studentId, Teacher teacher) {
return new Student(studentName, studentId);
}
getStudentForDBInseration(String studentName, long studentId, Teacher teacher) {
Student student = getStudent(studentName, studentId);
student = teacher;
//some entity frameworks need the student to be in the teachers student list
//so you might need to add the student to the teachers student list
teacher.addStudent(student);
}
https://stackoverflow.com/questions/302912
复制相似问题