【问题标题】:Update Model From Database (Database First)从数据库更新模型(数据库优先)
【发布时间】:2011-07-20 07:36:17
【问题描述】:

我正在使用带有 EF4.1 的 MVC3 VS2010,我使用 SQL Server 创建了我的数据库并将其导入到 MVC3 Web 应用程序。

我在这里遇到了一个挑战,当我从数据库更新模型时,我确实丢失了所有模型文件修改,例如,如果我在某些模型中使用属性进行验证,或者所有这些都被新模型属性覆盖.

是否可以在不丢失模型信息的情况下从数据库更新模型?

我应该在哪里对我的模型定义验证而不是直接使用模型的文件?

【问题讨论】:

    标签: entity-framework asp.net-mvc-3


    【解决方案1】:

    更新:由于这仍然比较流行,我为此创建了一篇博文。

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

    如果您想验证您的模型,而不是使用 viewModel,请使用部分类来定义验证属性。例如:

    假设你有一个类似的模型

    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,但这对我来说不实用。
    • 不,您只需要为新属性定义验证,无论如何您都必须这样做。部分类和元数据类不会被覆盖或替换
    • 对不起,我应该更清楚一点,在单独的文件中定义您的部分类和元数据类,而不是在自动生成的文件中。我会更新我的答案
    • 没问题,很高兴能帮上忙
    • 您在 [MetadataTypeAttribute(typeof(UserMetadata)] 上缺少一个结束 )
    【解决方案2】:

    不,每次都会重新生成文件。

    所有类都定义为部分类,因此您可以使用 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 提供了很大的帮助。
    • 这里的 MetadataType 和仅仅使用 : 关键字来扩展接口有什么不同吗?
    【解决方案3】:

    任何设计器的第一条规则是:它会生成任何你不能修改的代码,因为它会在你下次更新设计器中的任何东西时被完全删除。

    所有生成的类都是部分的,因此您可以创建自己的部分部分并将您的自定义逻辑放在那里。您显然不能将属性添加到自动生成部分中定义的属性。在数据注释的情况下,可以通过buddy classes 或自定义 T4 模板,该模板将包含您自己的逻辑来决定在代码生成期间应添加哪些数据注释。这两种情况大多被认为是一种不好的做法,因为每个视图都应该有单独的视图模型,并且该视图完全需要验证。

    【讨论】:

      【解决方案4】:

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

      示例:

      元数据:随处创建

      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; }
      }
      

      主类

      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; }
        }
      }
      

      部分使用元数据类型

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

      如果您在同一个 NameSpace 中创建 Class Partial 时遇到问题?别担心:

      1. 创建文件夹
      2. 在此文件夹中创建 Class Partial
      3. 在 MainClass 的同时更改命名空间

      【讨论】:

        猜你喜欢
        • 2023-04-01
        • 2018-02-26
        • 2013-03-13
        • 2015-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-23
        • 2016-12-08
        相关资源
        最近更新 更多