以下使用在Entity Framework Code First

 Entity Framework Code First 利用一种被称为约定(Conventions)优于配置(Configuration)的编程模式允许你使用自己的 domain classes 来表示 EF 所依赖的模型去执行查询、更改追踪、以及更新功能,这意味着你的 domain classes 必须遵循 EF 所使用的约定。然而,如果你的 domain classes 不能遵循 EF 所使用的约定,此时你就需要有能力去增加一些配置使得你的 classes 能够满足 EF 所需要的信息。

  Code First 提供了两种方式来配置你的类:

  • DataAnnotations, 使用简单属性;
  • Fluent API, 以编程命令行式的方式来描述你的配置

  本文将关注 DataAnnotations(位于命名空间 System.ComponentModel.DataAnnotations

  为了便于示例,我们先创建两个类:BlogPost

  以上类都是遵循约定的,但是你也可以使用 annotations EF 提供更多的信息

Key主键

  EF 依赖于每一个实体都有一个主键从而能够追踪实体。 在约定下,主键是通过寻找名称为 ID  ClassName + ID 的属性确定。那么如果类中没有此类的属性呢?我们把类改造如下(把 Id 改为 PrimaryTrackingKey

  此时如果我们添加 Scaffolded 会出现如下错误

  我们需要使用 key annotation 确定哪一个属性是主键

  我们使用 Code First's Database Generation 功能看看数据库的情况

Required非空

  用于指示字段非空

  运行看一下结果

  我们在看一下后台数据库情况

MaxLength and MinLength长度限制

  顾名思义,就是限制字段的长度

  看一下后台数据库

  运行看结果

NotMapped忽略

  类中有些属性,如通过计算获得或其它列的合并而来的,我们并不希望其记录在数据库中,此时就可以使用 NotMapped Annotation

  对于类也是一样的

ComplexType复杂类型

  一般这种情况是不常见的:类中包含另一个类即一个完整的实体是由一系列类的集合来描述。例如我们在我们的模型中增加一个叫 BlogDetails 的类

  注意 BlogDetails 不包含任何主键属性, 在领域驱动设计中被称为值对象,而在 EF 中则被称为复杂类型(ComplexType). Complex Types 是无法自我追踪的,但是我们可以通过 ComplexType Annotation 来改变这种尴尬

  可以看到,在数据库中表 Blog 包含 BlogDetails 的所有两个属性,默认列名前缀为 complex typeBlogDetails

 

ConcurrencyCheck并发检查

   ConcurrencyCheck Annotation 允许你可以在一个或多个属性上设置一个标记用于当用户更新或删除实体时做并发检查。

  如果此时同时对此列进行更新,则会抛出异常 DbUpdateConcurrencyException 

TimeStamp时间戳

  通常用行版本号或时间戳来检查并发,除了使用 ConcurrencyCheck Annotation, 还可以使用更为精确的 TimsStamp, 前提是这个属性的类型是字节数组(byte array). Code First 在对待 TimsStamp 属性和 ConcurrencyCheck 属性是一样的,只不过能确保数据库中生成的字段是 non-nullable

  在一个给定的类中只能有一个 TimsStamp 属性

  看一下后台数据库

Table and Column表/列名

  指定匹配到数据库的表/列名

  可以看到表/列名已更改

DatabaseGenerated自增长

  

  DatabaseGeneratedOption 有三个选项:

  • DatabaseGeneratedOption.Computed 在用 Code First 生成数据库的时候你可以在 byte 或 timestamp 列上使用 DatabaseGenerated Annotation,否则就应该在数据库存在的情况下使用因为如果数据库不存在,此时 Code First 不知道为计算列(Computed Column)选择使用什么样的公式 
  • DatabaseGeneratedOption.Identity 如果主键为 integer 型,则数据库默认为自增长(效果等同于设置DatabaseGeneratedOption.Identity), 如果主键是 GUID 类型,则要显式设置自增长
  • DatabaseGeneratedOption.None 如果不想自增长,可设置成 DatabaseGeneratedOption.None

ForeignKey 外键

  

  看看数据库

InverseProperty属性反转

  InverseProperty 一般使用在当类间有多重关系的时候。

  例如在 Post 中你可能不仅需要追踪谁写的也还要追踪有谁编辑了博客

  此时你会看到后台数据库有四个外键 Person_Id, Person_Id1, CreatedBy_Id and UpdatedBy_Id 

  为了解决这个问题,我们可以使用 InverseProperty annotation 来明确属性间的指向

  再一次看看数据库,情况已经发生了变化

以下用于验证数据

来自:https://msdn.microsoft.com/zh-cn/library/ee256141(VS.100).aspx

如何:使用 DataAnnotations 特性验证模型数据

Visual Studio 2010

本主题阐释了如何使用 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据模型中的各个字段的验证。 这些特性用于定义常见的验证模式,例如范围检查和必填字段。 System.ComponentModel.DataAnnotations 特性使 MVC 能够提供客户端和服务器验证检查,而无需您进行额外的编码。

System.ComponentModel.DataAnnotations 特性可用于实体数据模型 (EDM)、LINQ to SQL 和其他数据模型。 还可以创建自定义验证特性。 有关更多信息,请参见如何:使用自定义特性在数据模型中自定义数据字段验证

与本主题对应的包含源代码的 Visual Studio 项目可从 Download(下载)网页获得。

下图显示了客户端验证失败时自动显示在浏览器中的错误消息。

为响应验证错误而显示在浏览器中的消息

使用 DataAnnotations 特性添加验证

  1. 向项目添加类以包含分部类定义。 有关更多信息,请参见如何:在数据模型中自定义数据字段验证

  2. 向与正在使用的数据模型的命名空间匹配的分部类添加一个命名空间声明。

    注意

    在分部类中使用的不正确的命名空间会导致裸分部类,这是一种与任何其他类都不关联的分部类。 裸分部类是数据模型无法识别 DataAnnotations 特性的常见原因。 若要避免此问题,可以复制数据模型代码中的命名空间以确保您具有正确的命名空间。

  3. 命名分部类以匹配表示数据模型中的表的类声明,并将其粘贴到新的类文件中。

    注意

    类名称完全匹配是非常重要的。 确保分部类的名称匹配的最简单方法就是复制它。

    下面的示例显示了 AdventureWorksLT_2008 示例数据库中的 Product 表的分部类。 在本示例中,由 MvcDA 命名空间表示数据库。

     
    using System.ComponentModel.DataAnnotations;
    namespace MvcDA {
    [MetadataType(typeof(ProductMD))]
    public partial class Product {
    public class ProductMD {
    [StringLength(50),Required]
    public object Name { get; set; }
    [StringLength(15)]
    public object Color { get; set; }
    [Range(0, 9999)]
    public object Weight { get; set; }
    // public object NoSuchProperty { get; set; }
    }
    }
    }
    注意

    类中包括名为 NoSuchProperty 的属性并已将其注释掉。 可以如本主题后面所述,将此属性用来测试分部类。

  4. 创建一个关联类(有时称为“合作者类”),该类包含表示表的分部类的属性。

    关联类可以有任意名称,但习惯的做法在表类名称的后面追加“MD”或“MetaData”。 关联类必须用于 EDM 或 LINQ-to-SQL 模型,因为 CLR 类型不能用新的特性标记现有的属性。 如果直接使用 CLR 对象(有时称为“简单传统 CLR 对象 (POCO)”类型),则可以将特性直接应用于模型。

  5. 通过使用 MetadataTypeAttribute 特性将新类与表类关联。

    在前面的示例中,以下代码行将新类与表类关联:

     
    [MetadataType(typeof(ProductMD))]
    
  6. System.ComponentModel.DataAnnotations 特性应用于属性。 可以将任意数量的特性应用于每个属性。

如果无法识别您应用的数据批注,则应验证是否可以在项目中识别分部类。 以下过程建议了一种测试类的方法。

测试分部类

  1. 将一个属性添加到分部类,其名称与相应的数据模型中的属性不匹配。

    例如,取消对前一过程的示例中显示的 NoSuchProperty 属性的注释。

  2. 运行项目并输入要验证的数据。

    如果可以识别分部类,则在进行验证时,将会引发 InvalidOperationException 异常并显示如下类似的消息:

    类型“MvcDA.Product”的关联元数据类型包含下面的未知属性或字段:NoSuchProperty。 请确保这些成员的名称与主类型中的属性名称相匹配。

    如果分部类为裸分部类,则不会引发异常。 在这种情况下,检查分部类名称以确保它与数据模型中相应的类名称匹配,并且使用了正确的命名空间。

  3. 删除在分部类中添加的用于测试的属性。

在添加服务器端验证后,可以通过包括必要的 JavaScript 验证文件和启用客户端验证来添加客户端验证。

添加客户端验证

  • 向包含要验证的元素的视图添加对 JavaScript 验证文件的引用。 (常见做法是在 Site.master 文件中包括这些引用,使其应用于每个视图。)

    下面的示例演示如何引用为了包括客户端验证所需要的 JavaScript 文件。 (在此示例中,引用了库的调试版本。)该示例还演示如何调用 EnableClientValidation 方法以便启用客户端验证。 启用客户端验证的常见方法是向 Site.master 文件中添加下面的代码。 但是,也可以将此代码添加到实现客户端验证的视图页面中。 如果在母版页中包括下面的代码,则每个视图将自动启用客户端验证。

     
    <head runat="server">
    <script src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>" type="text/javascript"></script>
    <script src="<%= Url.Content("~/Scripts/MicrosoftMvcAjax.debug.js") %>" type="text/javascript"></script>
    <script src="<%= Url.Content("~/Scripts/MicrosoftMvcValidation.debug.js") %>" type="text/javascript"></script>
    <% Html.EnableClientValidation();%>
    </head>

若要编译代码示例,需要以下组件:

  • Microsoft Visual Studio 2008 Service Pack 1 或 Visual Web Developer 2008 速成版 Service Pack 1。

  • AdventureWorksLT_2008 示例数据库。 有关如何下载和安装 SQL Server 示例数据库的信息,请参见 CodePlex 站点上的 Microsoft SQL Server Product Samples: Database(Microsoft SQL Server 产品示例:数据库)。 请确保针对所运行的 SQL Server 版本(Microsoft SQL Server 2005 或 Microsoft SQL Server 2008)安装了正确版本的示例数据库。

  • 一个 MVC 应用程序,它具有从 AdventureWorksLT_2008 示例数据库创建的 EDM。 有关更多信息,请参见 ASP.NET 网站上的教程 Creating Model Classes with the Entity Framework(使用实体框架创建模型类)。

asp.net mvc5 step by step(二)——Data Annotations(data 注释)的更多相关文章

  1. ASP.NET MVC5 网站开发实践(二) Member区域–管理列表、回复及删除

    本来想接着上次把这篇写完的,没想到后来工作的一些事落下了,放假了赶紧补上. 目录: ASP.NET MVC5 网站开发实践 - 概述 ASP.NET MVC5 网站开发实践(一) - 项目框架 ASP ...

  2. ASP.NET MVC5 网站开发实践(二) Member区域 - 修改及删除文章

    上次做了显示文章列表,再实现修改和删除文章这部分内容就结束了,这次内容比较简单,由于做过了添加文章,修改文章非常类似,就是多了一个TryUpdateModel部分更新模型数据.   目录: ASP.N ...

  3. ASP.NET MVC5 网站开发实践(二) Member区域 - 添加文章

    上次把架构做好了,这次做添加文章.添加文章涉及附件的上传管理及富文本编辑器的使用,早添加文章时一并实现. 要点: 富文本编辑器采用KindEditor.功能很强大,国人开发,LGPL开源,自己人的好东 ...

  4. ASP.NET MVC5 网站开发实践(二) Member区域–我的咨询列表及添加咨询

    上次把咨询的架构搭好了,现在分两次来完成咨询:1.用户部分,2管理部分.这次实现用户部分,包含两个功能,查看我的咨询和进行咨询. 目录: ASP.NET MVC5 网站开发实践 - 概述 ASP.NE ...

  5. ASP.NET MVC5 网站开发实践(二) Member区域 - 咨询管理的架构

    咨询.留言.投诉等功能是网站应具备的基本功能,可以加强管理员与用户的交流,在上次完成文章部分后,这次开始做Member区域的咨询功能(留言.投诉都是咨询).咨询跟文章非常相似,而且内容更少.更简单. ...

  6. ASP.NET MVC5 网站开发实践(二) Member区域 - 全部文章列表

    显示文章列表分两块,管理员可以显示全部文章列表,一般用户只显示自己的文章列表.文章列表的显示采用easyui-datagrid.后台需要与之对应的action返回json类型数据   目录 ASP.N ...

  7. ASP.NET MVC5 网站开发实践(二) Member区域 - 文章管理架构

    上次把member的用户部分完成,现在开始做文章管理部分.文章部分根据涉及显示现实文章列表,发布文章,修改文章,删除文章等功能.最终的实现目标是使用权限来控制用户是否能进行相应操作,管理员权限的会显示 ...

  8. ASP.NET MVC5 网站开发实践(二) Member区域 - 用户部分(3)修改资料、修改密码

    在上一篇博客中实现了用户的注销和登录,其实代码里落了点东西,就是用户登录要更新最后一次登录时间和登录IP,这次补上.今天做修改资料和修改密码,TryUpdateModel是新用到的东西. 目录: AS ...

  9. ASP.NET MVC5 网站开发实践(二) Member区域 - 用户部分(2)用户登录、注销

    上次实现了用户注册,这次来实现用户登录,用到IAuthenticationManager的SignOut.SignIn方法和基于声明的标识.最后修改用户注册代码实现注册成功后直接登录. 目录: ASP ...

  10. ASP.NET MVC5 网站开发实践(二) Member区域 - 用户部分(1)用户注册

    上一次把基本框架搭建起来了,这次开始整Web部分,终于可以看到界面了小激动一下.web项目部分从用户功能开始,基本有注册,登录.注销.查找.查看.删除等涉及Member区域和Manage区域. 目录: ...

随机推荐

  1. 警告: The web application [ROOT] appears to have started a thread named [Thread-48] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:

    1. 问题描述 tomcat跑web项目(其中依赖java项目) 出现大量上述警告 项目起不来 关键字 memory leak 内存泄漏 2. 解决方案 难道是程序写的有问题? 最终 将tomcat ...

  2. java.util.concurrent.CyclicBarrier 使用

    1.概述 java.util.concurrent.CyclicBarrier(循环的栅栏), 构造时设置一个计数器数(count), 各线程通过调用barrier.await()进入等待,并且计数+ ...

  3. vue2.0中v-on绑定自定义事件的理解

    vue中父组件通过prop传递数据给子组件,而想要将子组件的数据传递给父组件,则可以通过自定义事件的绑定. 每个Vue实例都实现了[事件接口],即: 1.使用 $on(eventName) 监听事件 ...

  4. [转]webapi部署在IIS7.5报404的解决方案

    1.iis 目录权限设置 2.转自:http://www.cnblogs.com/youlies/p/6042169.html 在web.config添加如下节点 <system.webServ ...

  5. 消息循环中的TranslateMessage函数和DispatchMessage函数,特别注意WM_TIMER消息

    原文:http://www.cnblogs.com/xingrun/p/3583357.html TranslateMessage函数 函数功能描述:将虚拟键消息转换为字符消息.字符消息被送到调用线程 ...

  6. Http重要知识点

  7. SQL Server ->> SQL Server 2016新特性之 -- sp_set_session_context存储过程和SESSION_CONTEXT函数

    sp_set_session_context存储过程和SESSION_CONTEXT函数出现在了SQL Server 2016 CTP3.0上.它俩配合起来的作用是sp_set_session_con ...

  8. Studying TCP's Throughput and Goodput using NS

    Studying TCP's Throughput and Goodput using NS What is Throughput Throughput is the amount of data r ...

  9. 【Leetcode】【Medium】Remove Duplicates from Sorted Array II

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...

  10. ubuntu 16.04 virtualbox could not insert 'vboxdrv': Required key not available 问题解决方法

    从 内核版本 4.4.0-20 开始,在开启了 Secure Boot 的电脑上,未注册的 kernel 模块不再允许执行,所以如果想在保持 Secure Boot 的情况下依然允许执行,我们需要做的 ...