EntityFramework Core 学习系列(一)Creating Model

摘要:
PublicclassMyDbContext:DbContext{//…protectedoverridevoid OnModelCreating{modelBuilder.Entity<TEntity>().Property.IsRequired();//…}//…}DataAnnotation或您可以使用数据注释在实体中直接配置:publicclassBlogs{publicstringBlogName{get;set;}[必需]publicstringUrl{get,FluentAPI˃DataAnnotations˃Conventions Include&Exclude在三种情况下,类或实体将被包括:Byconvention、开始在DbSet属性中显示的类型以及您的模型中包含的上下文。包括OnModelCreating方法中开始的类型实点。通过递归搜索发现的类型的导航属性开始的所有类型均包含在模型中。您可以通过DataAnnotation或Fluent API排除包含,示例如下follows://DataAnnotationsExampleBelow:publicclassBlogs{publicentBlogId{get;set;}publicBlogAuthorBlogAuthors{get;set;{[NotMapped]publicclassBlogAuthor{publicstringFirstName{get,set;}//…}//FluentAPI示例如下:publicclassMyDbContext:DbContext{publicDbSet<Blog>Blogs{get;set;}protectedoverrideOnModelCreating{modelBuilder.Ignore<BlogAuthor>();}}publicclassBlogs{{publicintBlogId{get,set;}}publicBlogAuthorBlogAuthors{get当然,除了排除/包含类之外,您还可以自己将相应的属性配置为follows://DataAnnotationsExampleBelow:publicclassBlogs{publicentBlogId{get;set;}publicBlogAuthorBlogAuthors{get(设置);}[NotMapped]publicDateTimeBlogAddedTime{get,set;}//FluentAPI示例如下:publicclassMyDbContext:DbContext{publicDbSet<Blog>Blogs{;get;set,}protectedoverrideOnModelCreating{modelBuilder.Entity<Blog}()。忽略;}public classBlogs{publicEventBlogId{get;set;}PublicBlogAuthor BlogAuthers{getpublicDateTimeBlogAddedTime{get;set;}Key关于EFCore中的密钥,根据规范,如果属性名为Id或以Id结尾,则将其配置为实体的主键。
EntityFramework Core 学习系列(一)Creating Model

Getting Started

使用Command Line 来添加 Package

dotnet add package Microsoft.EntityFrameworkCore.SqlServer 使用 -v 可以指定相应包的版本号。

使用dotnet ef 命令

 需要在.csproj 文件中包含下面引用

<ItemGroup>
	<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0"/>
</ItemGroup>

Creating a Model

Fluent API

 在继承至 DbContext 的子类中,重载 OnModelCreating() 方法进行Fluent API 的配置。

public class MyDbContext : DbContext
{
	//...
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    	modelBuilder.Entity<TEntity>()
    		.Property(b => b.Url)
    		.IsRequired();
    	//...
    }
    //...
}

Data Annotation

 或者可以使用数据注解直接在实体中进行配置:

public class Blogs
{
  	public string BlogName { get; set; }
  	[Required]
  	public string Url { get; set; }
}

关于配置的顺序规范,

Fluent API > Data Annotations > Conventions

Include & Exclude

 有下列三种情况类或实体会被包含:

  1. By convention, types that are exposed in DbSet properties on your context are included in your model.
  2. Types that are mentioned in the OnModelCreating method are also included.
  3. Any types that are found by recursively exploring the navigation properties of discovered types are also included in the model.

你可以通过 Data Annotation 或者 Fluent API 来 排除包含,示例如下:

//Data Annotations Example Below:
public class Blogs
{
  public int BlogId { get; set;}
  
  public BlogAuthor BlogAuthors { get; set;}
}

[NotMapped]
public class BlogAuthor
{
  public string FirstName { get; set;}
  //...
}

//Fluent API Example Below:
public class MyDbContext : DbContext
{
	public DbSet<Blog> Blogs { get; set;}
	
	protected override OnModelCreating(ModelBuilder modelBuilder)
    {
    	modelBuilder.Ignore<BlogAuthor>();
    }
}
public class Blogs
{
  public int BlogId { get; set;}
  
  public BlogAuthor BlogAuthors { get; set;}
}

public class BlogAuthor
{
  public string FirstName { get; set;}
  //...
}

当然除了可以排出/包含类之外, 还可以自己配置相应的属性如下:

//Data Annotations Example Below:
public class Blogs
{
  public int BlogId { get; set;}
  
  public BlogAuthor BlogAuthors { get; set;}
  
  [NotMapped]
  public DateTime BlogAddedTime { get; set;}
}

//Fluent API Example Below:
public class MyDbContext : DbContext
{
	public DbSet<Blog> Blogs { get; set;}
	
	protected override OnModelCreating(ModelBuilder modelBuilder)
    {
    	modelBuilder.Entity<Blog>()
    		.Ignore(b => b.BlogAddedTime);
    }
}
public class Blogs
{
  public int BlogId { get; set;}
  
  public BlogAuthor BlogAuthors { get; set;}
  
  public DateTime BlogAddedTime { get; set;}
}

Key

 关于EF Core 中的Key, 按照规范,如果一个属性命名为Id 或者 以Id结尾的都会被配置成该实体的主键。比如下面的这个:

public class TestClass
{
  public int Id { get; set; }
  
  //or
  public int MyId { get; set; }
}

或者你可以按照 Data Annotation 或者 Fluent API 来进行配置:

// Data Annotations
public class Car 
{
  [Key]
  public string CarLicense { get; set; }
  
  public string CarFrameCode { get; set;}
}

//Fluent API
//...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Car>()
    	.HasKey(c => c.CarLicense);
}
//...

// Multiple Properties to the key ,复合主键的配置只能用Fluent API
modelBuilder.Entity<Car>()
  	.HasKey(c => new { c.CarLicense, c.CarFrameCode });

Generated Values

 中文应该是叫值的自动生成吧,我也不清楚。EF Core 上 有三种 Value Generation Pattern。分别是

  1. No Value Generation

    No value generation means that you will always supply a valid value to be saved to the database. This valid value must be assigned to new entities before they are added to the context.

    值不自动生成,每个属性的值都需要指定,添加。这个我理解的意思应该是你保存到数据库里面的值,每个必须是有效的,并且需要指定。

  2. Value Generated on Add

    Value generated on add means that a value is generated for new entities.

    Depending on the database provider being used, values may be generated client side by EF or in the database. If the value is generated by the database, then EF may assign a temporary value when you add the entity to the context. This temporary value will then be replaced by the database generated value during SaveChanges().

    If you add an entity to the context that has a value assigned to the property, then EF will attempt to insert that value rather than generating a new one. A property is considered to have a value assigned if it is not assigned the CLR default value (null for string, 0 for int, Guid.Empty for Guid, etc.).

    属性的值在 添加到数据库时自动添加。

  3. Value Generated on Add or Update

    Value generated on add or update means that a new value is generated every time the record is saved (insert or update).

    Like value generated on add, if you specify a value for the property on a newly added instance of an entity, that value will be inserted rather than a value being generated. It is also possible to set an explicit value when updating.

    属性的值在 添加到数据库或者更新时自动添加。

 当当看着上面这三个,我其实并不知道这三个到底是什么意思,接下来会用例子来演示一下这些具体意思,以及使用规范。

By convention, primary keys that are of an integer or GUID data type will be setup to have values generated on add. All other properties will be setup with no value generation.(当主键为 Interger 或者 GUID类型事,该主键的值会自动生成。)

 下面用实例来模拟一下:

我们新建一个实体 Blogs 如下:

//Entity Blog 
public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
// Program.cs 
using (var db = new BookDbContext())
            {
                if (!db.Blogs.Any())
                {
                    var blog = new Blog
                    {
                        Url = "Https://q.cnblogs.com"
                    };
                    db.Blogs.AddRange(blog);
                    db.SaveChanges();
                }
            }

直接用在Program 用using 来演示效果,由于我们之前说到的主键为 Integer 类型的会自动生成值,所以数据库中的值大家可想而知,就是下面这个

EntityFramework Core 学习系列(一)Creating Model第1张

下面是用Data Annotation(数据注解)来演示的,也可以用Fluent API:

No Value Generation

如果我们不想让它自动生成的话呢,也有办法。向下面这样:

 public class Blog
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int BlogId { get; set; }
        public string Url { get; set; }
    }

我在 BlogId 上加上 DatabaseGeneratedOption.None 之后,我们再重新运行上面的程序,发现数据库的值如下所示:

EntityFramework Core 学习系列(一)Creating Model第2张

为什么是 0 的原因呢,其实上面已经解释过了:就是下面这句话

A property is considered to have a value assigned if it is not assigned the CLR default value (null for string, 0 for int, Guid.Empty for Guid, etc.). CLR 的默认值。

Fluent API 版本

modelBuilder.Entity<Blog>()
    .Property(b => b.BlogId)
    .ValueGeneratedNever();

Value Generated on Add

 比如我们还想在 Blog 实体里面加一个 更新时间 UpdateTime 属性

public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
  		[DataGenerated(DatabaseGeneratedOption.Identity)]
  		public DateTime UpdateTime { get; set;}
    }

当我们配置成上面这样,然后直接 dotnet run 时,发现程序报错了。

Unhandled Exception: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Microsoft.Data.Sqlite.SqliteException: SQLite Error 19: 'NOT NULL constraint failed: Blogs.UpdateTime'.

Setting Explicit Value 中在OnModelCreating 中配置,使其自动生成,但是本地我使用SQLite 时无法自动生成,报错。具体使用如下

   modelBuilder.Entity<Blog>()
                .Property(p => p.UpdateTime)
                .HasDefaultValueSql("CONVERT(date, GETDATE())");

Fluent API 版本

modelBuilder.Entity<Blog>()
    .Property(b => b.UpdateTime)
    .ValueGeneratedOnAdd();

Value generated on add or update (Data Annotations)

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime LastUpdated { get; set; }
}

Fulent API 版本

modelBuilder.Entity<Blog>()
    .Property(b => b.LastUpdated)
    .ValueGeneratedOnAddOrUpdate();

下面记录一下 dotnet ef 命令的使用

dotnet ef migrations add name

dotnet ef database update 

dotnet ef migrations remove 

dotnet ef database drop

免责声明:文章转载自《EntityFramework Core 学习系列(一)Creating Model》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Windows 下openssl安装与配置【实践】js实现windows系统日历下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

nacos产生大量日志处理

/我们发现nacos产生大量日志,浪费磁盘空间资源将配置文件nacos/conf/application.properties的生产日志功能关闭--进入配置文件vim./nacos/conf/application.properties--将true改为falseserver.tomcat.accesslog.enabled=true--重启nacos./n...

数据不平衡的相关

大多数常见的机器学习算法不能很好地处理不平衡的数据集。例如,搜索引擎的点击预测(点击页面往往占很小的比例)、电子商务中的产品推荐(正在购买的推荐产品的比例很低)、信用卡欺诈检测、网络攻击识别、癌症检测等。处理数据不平衡的方法主要有以下几种。2.数据级别2.1重新采样2.1.1欠采样(下采样)欠采样通过减少丰富类的大小来平衡数据集。它试图通过增加稀有样本的数量...

如何下载Chrome离线版EXE安装文件和MSI版安装文件

对于Chrome的稳定版本(官方版本),您只需添加“?”在Chrome的“最终用户许可协议”页面上的链接之后?Standalone=1对于Beta版和开发版Chrome,只需记住以下地址:http://dl.google.com/chrome/install/{versionnumber}/crome_安装程序中的版本号。exe表示要下载的Chrome版本号...

如何更改SQL Server2008默认数据库的存储路径

1.在安装SQlServer时,修改路径:当然,也可以修改共享函数目录和实例根目录。但是,我不知道共享函数目录和实例根目录是什么。...

zabbix监控华为交换机

xmlversion=“1.0”encoding=“UTF-8”?...