从数据库更新模型(数据库优先)

6
我正在使用MVC3 VS2010与EF4.1,我使用SQL Server创建了我的数据库,并将其导入到MVC3 Web应用程序中。
我在这里遇到了一个挑战,当我来自数据库更新模型时,我会失去所有模型文件的修改,例如,如果我在某些模型中使用属性进行验证等操作,所有这些都会被新模型属性覆盖。
有没有办法在不丢失模型信息的情况下从数据库更新模型?
或者
我应该在哪里定义模型的验证,而不是直接使用模型文件?
4个回答

11

更新:由于这仍然相对受欢迎,我已经在博客上发布了相关文章。

http://jnye.co/Posts/19/adding-validation-to-models-created-by-entity-framework-database-first-c

如果您想要验证您的模型,而不使用视图模型,请使用局部类来定义验证属性。例如:

假设您有一个像这样的模型:

public class User {
    public string Name { get; set; }
}
如果您想在字符串上设置长度验证器,则需要创建一个部分类并利用MetadataTypeAttribute(位于System.ComponentModel.DataAnnotations中)。
以下类应定义在它们自己的单独文件中,而不是放在与您的自动生成的模型相同的文件中。
[MetadataTypeAttribute(typeof(UserMetadata))]
public partial class User {
}

接下来,您可以将验证定义在 UserMetadata 类中,如下所示:

public class UserMetadata{
    [StringLength(50)]
    public string Name {get; set;}
}

编辑

我刚刚找到了这篇文章,它更详细地解释了解决方案。 http://themonitoringguy.com/tips-tricks/validating-microsoft-entity-framework-objects-c-mvc/


所以每次模型重新生成时,我都必须回到每个文件并重新定义我的[MetadataTypeAttribute(typeof())]属性。谢谢@NinjaNye,但这对我来说不实用。 - Shadi
不需要,您只需要为新属性定义验证,这是必须要做的。部分类和元数据类不会被覆盖或替换。 - NinjaNye
抱歉,我应该让这一部分更清晰些。请在一个单独的文件中定义您的部分类和元数据类,而不是在自动生成的文件中。我会更新我的回答。 - NinjaNye
1
你在[MetadataTypeAttribute(typeof(UserMetadata)]上缺少一个闭合的)。 - Danny Cullen
很好的发现 @DannyCullen,这个问题现在已经修复了。 - NinjaNye

3
不,文件将每次重新生成。
所有的类都被定义为partial,因此您可以使用MetadataTypeAttribute轻松地添加DataAnnotations。
假设您有一个名为User的类,定义如下:
public partial class User {
    public string Name {get;set;}
}

创建一个 IUser 接口。
public interface IUser {
   [Required]
   [DisplayName("User name")]
   string Name {get;set;}
}

然后扩展User类以指定将使用IUser作为元数据。

[MetadataType(typeof(IUser))]
public partial class User {} //Empty class body

感谢你,Bertand。你和@NinjaNye提供了巨大的帮助。 - Shadi
元数据类型在这里与使用“:”关键字扩展接口有什么不同吗? - Drazen Bjelovuk

1
任何设计师的第一条规则是:如果它生成了任何代码,您就不能修改它,因为下次更新设计器中的任何内容时,它将被完全删除。
所有生成的类都是partial的,因此您可以创建自己的部分,并在其中放置自定义逻辑。您显然无法向自动生成的部分中定义的属性添加属性。在数据注释的情况下,可以通过buddy classes或自定义T4模板来实现,该模板将包含您自己的逻辑,以决定在生成代码期间应添加哪些数据注释。这两种情况大多被认为是不好的做法,因为您应该对每个需要验证的视图拥有单独的视图模型。

1

请检查MainClass的命名空间是否与Partial相同,并具有相同的属性。这是我的解决方案。

例如:

元数据:在任何您想要的地方创建它

public class FormMetadata
{
    public int Id { get; set; }
    public string Description { get; set; }
    public Nullable<bool> IsEnable { get; set; }
    public Nullable<System.DateTime> CreationDate { get; set; }
    public int CompanieId { get; set; }
    public string RegularExpression { get; set; }

    public virtual ICollection<Field> Fields { get; set; }
    [JsonIgnore]
    public virtual Company Company { get; set; }
}

MainClass

namespace Transactions.Model
{
  public partial class Form
  {
      [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
      public Form()
      {
          this.Fields = new HashSet<Field>();
      }  
      public int Id { get; set; }
      public string Description { get; set; }
      public Nullable<bool> IsEnable { get; set; }
      public Nullable<System.DateTime> CreationDate { get; set; }
      public int CompanieId { get; set; }
      public string RegularExpression { get; set; }
      [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
      public virtual ICollection<Field> Fields { get; set; }
      public virtual Company Company { get; set; }
  }
}

使用MetadataType的部分

namespace Transactions.Model
{
    [MetadataTypeAttribute(typeof(FormMetadata))]
    public partial class Form
    {
    }
}

如果您在同一命名空间中创建类的部分类时遇到问题?不用担心:
  1. 创建一个文件夹
  2. 在此文件夹中创建类的部分类
  3. 将命名空间更改为MainClass相同的命名空间

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接