示例一
本例演示与索引有关的内容,模型:
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations { public class Post { public int Id { get; set; } public string Title { get; set; } [Index("PostRatingIndex")] public int BlogId { get; set; } } public class User { public int UserId { get; set; } [Index(IsUnique = true)] [StringLength(200)] public string Username { get; set; } public string DisplayName { get; set; } } public class Cell { public int Id { get; set; } public string Content { get; set; } [Index("IX_Location", 1, IsUnique = true)] public int Row { get; set; } [Index("IX_Location", 2)] [StringLength(5)] public string Column { get; set; } } }
生成的数据库表代码为:
------------------------------------------ CREATE TABLE [dbo].[Posts] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Title] NVARCHAR (MAX) NULL, [BlogId] INT NOT NULL, CONSTRAINT [PK_dbo.Posts] PRIMARY KEY CLUSTERED ([Id] ASC) ); GO CREATE NONCLUSTERED INDEX [PostRatingIndex] ON [dbo].[Posts]([BlogId] ASC); GO ------------------------------------------ CREATE TABLE [dbo].[Users] ( [UserId] INT IDENTITY (1, 1) NOT NULL, [Username] NVARCHAR (200) NULL, [DisplayName] NVARCHAR (MAX) NULL, CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([UserId] ASC) ); GO CREATE UNIQUE NONCLUSTERED INDEX [IX_Username] ON [dbo].[Users]([Username] ASC); GO ------------------------------------------ CREATE TABLE [dbo].[Cells] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Content] NVARCHAR (MAX) NULL, [Row] INT NOT NULL, [Column] NVARCHAR (5) NULL, CONSTRAINT [PK_dbo.Cells] PRIMARY KEY CLUSTERED ([Id] ASC) ); GO CREATE UNIQUE NONCLUSTERED INDEX [IX_Location] ON [dbo].[Cells]([Row] ASC, [Column] ASC); GO
Post类演示了在BlogId上定义一个名为PostRatingIndex的索引。
User类演示了如何定义一个唯一索引,注意这里没有指定索引的名称,系统按照格式IX_PropertyName生成索引名称。
Cell类演示多列索引,给每个列指定相同的名称,如果有索引选项要修改,只需要在第一个属性上指定。
对字符串string类型的属性建立索引,需要指定其长度,长度不能大于某个值。
示例二
本例演示外键,模型代码:
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations { public class Blog { [Key] public int PrimaryKey { get; set; } public string Title { get; set; } //导航属性 public virtual ICollection<Post> Posts { get; set; } } public class Post { public int Id { get; set; } public string Content { get; set; } //外键 public int BlogId { get; set; } //导航属性 [ForeignKey("BlogId")] public Blog Blog { get; set; } } }
这里,Blog的主键没有遵守主键的命名约定,在Post类的导航属性Blog上指定外键属性,其参数"BlogId"指的是Post类成员BlogId是外键列。
生成的数据库代码:
----------------------------------------------------------------------------------------- CREATE TABLE [dbo].[Blogs] ( [PrimaryKey] INT IDENTITY (1, 1) NOT NULL, [Title] NVARCHAR (MAX) NULL, CONSTRAINT [PK_dbo.Blogs] PRIMARY KEY CLUSTERED ([PrimaryKey] ASC) ); ----------------------------------------------------------------------------------------- CREATE TABLE [dbo].[Posts] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Content] NVARCHAR (MAX) NULL, [BlogId] INT NOT NULL, CONSTRAINT [PK_dbo.Posts] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_dbo.Posts_dbo.Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [dbo].[Blogs] ([PrimaryKey]) ON DELETE CASCADE ); GO CREATE NONCLUSTERED INDEX [IX_BlogId] ON [dbo].[Posts]([BlogId] ASC);
EF框架默认为外键列添加索引,以加快检索速度。
现在,将Post类中的ForeignKey标记从导航属性移动到外键属性上,微调代码:
public class Post { public int Id { get; set; } public string Content { get; set; } //外键 [ForeignKey("MyBlog")] public int BlogId { get; set; } //导航属性 public Blog MyBlog { get; set; } }
再次查看生成的数据库表:
CREATE TABLE [dbo].[Posts] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Content] NVARCHAR (MAX) NULL, [BlogId] INT NOT NULL, CONSTRAINT [PK_dbo.Posts] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_dbo.Posts_dbo.Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [dbo].[Blogs] ([PrimaryKey]) ON DELETE CASCADE ); GO CREATE NONCLUSTERED INDEX [IX_BlogId] ON [dbo].[Posts]([BlogId] ASC);
可见生成的代码是一样的,由此可见,外键标记就是在依赖表中建立外键属性与导航属性之间对应关联的。
示例三
本示例演示反转属性注解,此注解用于两个实体间有多个关系的情况,如一个文档有创建者,有更新者,这两者都是人。此时如下定义模型:
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace DataAnnotations { public class Person { public int Id { get; set; } [Index(IsUnique =true),StringLength(50)] public string Name { get; set; } //导航属性 [InverseProperty("CreatedBy")] public List<Document> CreatedDocuments { get; set; } [InverseProperty("UpdatedBy")] public List<Document> UpdatedDocuments { get; set; } } public class Document { public int Id { get; set; } public string Content { get; set; } //导航属性 public Person CreatedBy { get; set; } public Person UpdatedBy { get; set; } } }
在Person类的CreatedDocuments上有标记[InverseProperty("CreatedBy")],并且此属性是Document类型的集合,则可以翻译成Person类的CreatedDocuments导航属性是Document类的CreatedBy导航属性的反属性。
下面是生成的数据库:
CREATE TABLE [dbo].[People] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Name] NVARCHAR (50) NULL, CONSTRAINT [PK_dbo.People] PRIMARY KEY CLUSTERED ([Id] ASC) ); GO CREATE UNIQUE NONCLUSTERED INDEX [IX_Name] ON [dbo].[People]([Name] ASC); -------------------------------------------------------------------------------------- CREATE TABLE [dbo].[Documents] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Content] NVARCHAR (MAX) NULL, [CreatedBy_Id] INT NULL, [UpdatedBy_Id] INT NULL, CONSTRAINT [PK_dbo.Documents] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_dbo.Documents_dbo.People_CreatedBy_Id] FOREIGN KEY ([CreatedBy_Id]) REFERENCES [dbo].[People] ([Id]), CONSTRAINT [FK_dbo.Documents_dbo.People_UpdatedBy_Id] FOREIGN KEY ([UpdatedBy_Id]) REFERENCES [dbo].[People] ([Id]) ); GO CREATE NONCLUSTERED INDEX [IX_CreatedBy_Id] ON [dbo].[Documents]([CreatedBy_Id] ASC); GO CREATE NONCLUSTERED INDEX [IX_UpdatedBy_Id] ON [dbo].[Documents]([UpdatedBy_Id] ASC);
EF在外键表Documents中生成外键列的名字为:导航属性_Id。