首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实体框架验证与使用

实体框架验证与使用
EN

Stack Overflow用户
提问于 2008-11-19 18:41:15
回答 5查看 2K关注 0票数 13

我知道有一个AssociationChanged事件,但是,这个事件在关联建立后触发。没有AssociationChanging事件。因此,如果出于某种验证的原因,我想抛出一个异常,我如何做到这一点并返回到我的原始值?

此外,我希望根据来自其他实体的信息为我的实体设定默认值,但只有当我知道实体被插入到数据库时才会这样做。我该如何区分它和被实例的对象之间的区别,因为它即将基于现有的数据填充?我应该知道吗?这是在我的实体业务逻辑之外考虑的业务逻辑吗?

如果是这样的话,那么我应该设计控制器类来包装所有这些实体吗?我担心的是,如果我返回一个实体,我希望客户机能够访问这些属性,但是我希望对如何设置、默认等等的验证保持严格的控制。我看到的每个示例都引用上下文,这超出了我的敌意部分类验证的范围,对吗?

顺便说一句,我看了EFPocoAdapter,为了我的生命,我无法决定如何从我的POCO类中填充列表.有人知道我是如何从EFPoco类获得上下文的吗?

EN

回答 5

Stack Overflow用户

发布于 2010-12-23 19:11:45

这是对我留下的一条评论的回应。希望这能回答你的问题,希米。评论一下,如果它不回答你的问题,我会把它缩短或者删除。

您需要在类上实现INotifyPropertyChanging和INotifyPropertyChanged接口(除非它类似于实体框架对象,我认为它是在内部实现的)。

在为该属性设置值之前,需要使用NotifyPropertyChanging.PropertyChanging构造函数中属性的名称引发PropertyChangingEventArgs事件。

设置此值后,需要再次使用在NofityPropertyChanged.PropertyChanged构造函数中引发的属性的名称引发PropertyChangedEventArgs事件。

然后,您必须处理PropertyChanging和PropertyChanged事件。在PropertyChanging事件中,您需要缓存该值。在PropertyChanged事件中,您可以比较并抛出异常。

要从PropertyChanging/PropertyChanged事件args获取属性,您需要使用relf辙。

代码语言:javascript
运行
复制
// 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#本身描述性要强得多--准确地显示了正在处理的是什么。

票数 2
EN

Stack Overflow用户

发布于 2009-08-19 17:36:20

关于您的第一个问题,我只是将对关联的更改作为业务逻辑来实现。例如,如果您添加一个具有多个学生的教师类,则不要添加

代码语言:javascript
运行
复制
aTeacher.Students.Add(new Student)

相反,创建一个AddStudent方法

代码语言:javascript
运行
复制
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加载数据,它们将被覆盖。

祝好运

票数 0
EN

Stack Overflow用户

发布于 2009-09-23 21:46:10

创建一个工厂,根据需要为您生成实例,如下所示:

代码语言:javascript
运行
复制
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);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/302912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档