zoukankan      html  css  js  c++  java
  • Code First DataAnnotations 介绍

    Data annotation特性是在.NET 3.5中引进的,给ASP.NET web应用中的类提供了一种添加验证的方式。Code First允许你使用代码来建立实体框架模型,同时允许用Data annotation特性来配置类和属性的某些特性。

    实体内的关系

    Key

    EF框架要求每个实体必须有主键字段,他需要根据这个主键字段跟踪实体。CodeFirst方法在创建实体时,也必须指定主键字段,默认情况下属性 被命名为ID、id或者[ClassName]Id,将映射为数据表中的主键如果没有类似的命名,并且也未显示指明主键,则生成失败,引发异常。如果想要 自定义主键列名,则可以使用Key注释

    [Key]
    publicint MyId { get; set; }

    Required

    当要求数据库在字段,不能为空时

    [Required]
    publicstring BookTitle { get; set; }

    MaxLength 、MinLength

    设置数据库字段的长度范围

    [MaxLength(10),MinLength(6)]
    publicstring Password { get; set; }

    NotMapped

    当创建数据表时,用此属性修饰的属性,不会被创建为数据表字段

    [NotMapped]
    publicint MyProperty { get; set; }

    ComplexType

    Complex属性是将一个对象做为另一个对象的属性。映射到数据库中则子对象表现为多个属性字段。具体可参考:处理实体complex属性

    [ComplexType]
    publicclass Publisher
    {
    publicstring PublisherName { get; set; }
    publicstring PublisherAddress { get; set; }
    } 

    ConcurrencyCheck

    并发检查允许你标识一个或者多个属性在实体更新时,要进行检查是否与原实体一致。并发检查依懒于OriginalValue,在WEB应用程序中, 通常是某一用户获取数据实体后,会与数据库断开连接,这时,如果另一用户也获得了实体并进行了更新新操作,那么当最初用户进行再更新时,会自动进行并发检 查,根据被标识ConcurrencyCheck属性的OriginalValue,判断原实体是否存在。如果不存在,则在SaveChanges方法是 会引发一个异常。

    下面的例子是Book实体的BookTitle属性被标识为ConcurrencyCheck

    [Required,ConcurrencyCheck]
    publicstring BookTitle { get; set; }

    则下面代码模拟并发现象:

    Book book = db.Books.Find(1);
    //显示表明数据实体被修改
    db.Entry(book).State = System.Data.EntityState.Modified;
    db.Entry(book).Property(b
    => b.BookTitle).OriginalValue ="DataAnnotations";

    //这么代码会引发异常
    db.SaveChanges();

    引发异常如下图:

    用SQL Profile监控,数据库执行了如下

    update[dbo].[MyBook]
    set[BookTitle]=@0
    where (([MyId]=@1) and ([BookTitle]=@2))
    ', N'@0nvarchar(4000),@1int,@2nvarchar(4000)',
    @0 = N
    'EF4.1 Code First', @1 = 1, @2 = N'DataAnnotations'

    TimeStamp 与 DatabaseGenerated

    TimeStamp是比ConcurrencyCheck更通用的监控并发的字段,在实体中通常一个类型为字节数组的字段表示,一个实体类只能有一个TimeStamp字段,并且他通常与DatabaseGenerated联合使用,DatabaseGenerated表明是由数据库自动生成,他需要DatabaseGeneratedOption枚举来做为数据库生成时参数,DatabaseGeneratedOption枚举包含三个值 Computed 由数据库自动计算,Identity自动增长,None数据库不做处理。

    [Timestamp,DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public Byte[] TimeStamp { get; set; }

    TimeStamp与ConcurrencyCheck用法类似

    Book book = db.Books.Find(1);

    //模拟另一个用户对同一数据实体进行更新
    db.Database.ExecuteSqlCommand("update mybook set Booktitle='EF' where MyId=1");

    book.BookTitle
    ="New Title";
    db.SaveChanges();
    同样,在SaveChanges()时,也会引发DbUpdateConcurrencyException。

    Table

    CodeFirst 方法默认以实体类名复数形式做为数据表名,Table注释允许自定义表名

    [Table("MyBook")]
    publicclass Book

    Column

    CodeFirst 方法默认以实体类属性名做为列名,Column注释允许自定列名及数据类型

    [Column("BlogDescription", TypeName ="ntext")]
    publicstring Description { get; set; }

    好,来个综合示例,看一下运行结果,对照理解一下 

    [Table("MyBook")]
    publicclass Book
    {
    [Key]
    publicint MyId { get; set; }

    [MaxLength(
    10), MinLength(6)]
    publicstring KeyWord { get; set; }

    [Required,MaxLength(
    50)]
    publicstring BookTitle { get; set; }

    [NotMapped]
    publicint MyProperty { get; set; }

    public Publisher Publisher { get; set; }

    [Column(
    "BlogDescription", TypeName ="ntext")]
    publicstring Description { get; set; }

    [Timestamp,DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public Byte[] TimeStamp { get; set; }

    }
    [ComplexType]
    publicclass Publisher
    {
    publicstring PublisherName { get; set; }
    publicstring PublisherAddress { get; set; }
    }

    生成数据表如图:

    实体间的关系

    ForeignKey

    Code first默认情况下会自动建立实体之间的关系

    publicpartialclass BlogUser
    {

    publicint BlogUserId { get; set; }
    publicstring BlogName { get; set; }
    publicvirtual ICollection<Post> Posts { get; set; }
    }

    publicpartialclass Post
    {
    publicint PostId { get; set; }
    publicstring PostTitle { get; set; }
    publicint BlogUserId { get; set; }
    publicvirtual BlogUser BlogUser { get; set; }
    }

    以上这种代码写法,CodeFirst方法,在生成数据时,会在Post实体中去查找BlogUserId属性(也就是以BlogUser实体的主 键),找到后,则会用此属性与BlogUser实体进行关联。如果没有找到,他会在自动创建一个列,并命名为BlogUser.BlogUserId,作 为与BlogUser实体的关联属性。

    用代码描述一下,将上面的代码修改成:  

    publicpartialclass BlogUser
    {
    publicint BlogUserId { get; set; }
    publicstring BlogName { get; set; }
    publicvirtual ICollection<Post> Posts { get; set; }
    }

    publicpartialclass Post
    {
    publicint PostId { get; set; }
    publicstring PostTitle { get; set; }
    //期望用这个作为外键关联
    publicint BlogId { get; set; }
    publicvirtual BlogUser BlogUser { get; set; }
    }

    但实际生成的数据表如图:

    这时,可以看出,CodeFirst方法,并没有按我们所设想的那样,以BlogId做为外键,要完成这个想法,需要借助ForeignKey特性,将代码修改如下

    publicpartialclass Post
    {
    publicint PostId { get; set; }
    publicstring PostTitle { get; set; }
    //期望用这个作为外键关联
    publicint BlogId { get; set; }
    [ForeignKey(
    "BlogId")]
    publicvirtual BlogUser BlogUser { get; set; }
    }

    这时,即可达到预期的目的。

  • 相关阅读:
    nodejs内存溢出解决方法
    mongodb副本集与分片结合
    node加密
    守护进程,互斥锁,IPC,队列,生产者与消费者模型
    并发编程
    粘包问题
    socket编程
    xml模块
    网络编程
    异常处理
  • 原文地址:https://www.cnblogs.com/wmlunge/p/2852939.html
Copyright © 2011-2022 走看看