Programming Entity Framework CodeFirst -- 约定和属性配置
2015-03-04 22:47 stoneniqiu 阅读(1369) 评论(0) 编辑 收藏 举报
Data Annotation
|
MinLength(nn)
MaxLength(nn)
StringLength(nn)
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName).HasMaxLength(nn)
|
在SQL Server中,string会转换为nvarchar(max),bit会转换为varbinary(max) 如果是SQL CE这里的最大值会变成4000(毕竟人家是嵌入式数据库). 通过MinLength等来限制字段在数据库中的长度。MinLength和MaxLength会受到EntityFramework的验证,不会影响到数据库。
[StringLength(500,MinimumLength= 10)] public string Description { get; set; }
Data Type
Data Annotation
|
Column(TypeName=“xxx”)
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName)
.HasColumnType (“xxx”)
|
[Column(TypeName = "image")] public byte[] Photo { get; set; }
Nullability
Data Annotation
|
Required
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName).IsRequired
|
[Required] public string Name { get; set; }
Keys
Data Annotation
|
Key
|
Fluent
|
Entity<T>.HasKey(t=>t.PropertyName)
|
EF需要每个实体必须拥有一个Key,context会根据key来跟踪对象。而且默认是自动递增的。
Database-Generated
Data Annotation
|
DatabaseGenerated(DatabaseGeneratedOption)
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption)
|
[Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int DestinationId { get; set; }
DatabaseGeneratedOption 为None可以关闭自动增加。
TimeStamp或RowVersion
Data Annotation
|
TimeStamp
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName).IsRowVersion()
|
timestamp和rowversion是同一个数据类型的不同叫法,不同的数据库显示不同
[Timestamp] public byte[] RowVersion { get; set; }
时间戳:数据库中自动生成的唯一二进制数字,与时间和日期无关的, 通常用作给表行加版本戳的机制,当行数据发生修改,时间戳会自动增加。存储大小为 8个字节。一个表只有一个时间戳列,不适合做主键,因为其本身是变化的。
在控制并发时起到作用:
用户A/B同时打开某条记录开始编辑,保存是可以判断时间戳,因为记录每次被更新时,系统都会自动维护时间戳,所以如果保存时发现取出来的时间戳与数据库中的时间戳如果不相等,说明在这个过程中记录被更新过,这样的话可以防止别人的更新被覆盖.
Non-Timestamp for Concurrency
Data Annotation
|
ConcurrencyCheck |
Fluent
|
Entity<T>.Property(t=>t.PropertyName).IsConcurrencyToken() |
对于那些没有时间戳的数据库中也提供并发检查。避免造成同时修改造成的冲突。和上面的Timestamp一样,当模型发生改变写入到数据库的时候,数据库不但通过key找到了这一行数据,还会比对标记了Concurrency字段的值是否是原来的值。
public class Person { public int PersonId { get; set; } [ConcurrencyCheck] public int SocialSecurityNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } //.... private static void UpdatePerson() { using (var context = new BreakAwayContext()) { var person = context.People.FirstOrDefault(); person.FirstName = "Rowena"; context.SaveChanges(); } }
SQL:
exec sp_executesql N'update [dbo].[People] set [FirstName] = @0 where (([PersonId] = @1) and ([SocialSecurityNumber] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 int',@0=N'Rowena',@1=1,@2=12345678
Non-Unicode Database Types
Data Annotation
|
unavailable
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName).IsUnicode(boolean)
|
Property(l => l.Owner).IsUnicode(false);
默认情况下,所以string都会映射成数据库中的Unicode类型。data Annotation 不支持。
Precision and Scale of Decimals
精度定义:
Data Annotation
|
unavailable
|
Fluent
|
Entity<T>.Property(t=>t.PropertyName).HasPrecision(n,n)
|
Property(l => l.MilesFromNearestAirport).HasPrecision(8, 1);
上面表示MilesFromNearestAirport是八位数,保留一位小数。data Annotation 不支持。
complex type
Complex Type需要满足3个条件:1.没有key(Id),2.complex类型只能包含原始属性(primitive properties),3.当它用到别的类中时,只能是非集合(non-collection)形式。
下面的Address就是一个complex type
public class Address { //public int AddressId { get; set; } public string StreetAddress { get; set; } public string City { get; set; } public string State { get; set; } public string ZipCode { get; set; } } public class Person { public int PersonId { get; set; } public int SocialSecurityNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public Address Address { get; set; } }
生成的表如下。
[ComplexType] public class Address { public int AddressId { get; set; } public string StreetAddress { get; set; } public string City { get; set; } public string State { get; set; } public string ZipCode { get; set; } }
Api :
modelBuilder.ComplexType<Address>().Property(p => p.StreetAddress).HasMaxLength(150);
More Complicated Complex Types
public class PersonalInfo { public Measurement Weight { get; set; } public Measurement Height { get; set; } public string DietryRestrictions { get; set; } } public class Measurement { public decimal Reading { get; set; } public string Units { get; set; } } public PersonalInfo Info { get; set; }
Person包含PersonInfo,PersonInfo包含两个Measurement。先在构造函数中初始化:
public Person() { Address = new Address(); Info = new PersonalInfo { Weight = new Measurement(), Height = new Measurement() }; }
这时运行会报错,说PersonInfo 没有定义主键。因为他包含的两个Measurement不是原始类型(primitive types)。


public class AddressConfiguration : ComplexTypeConfiguration<Address> { public AddressConfiguration() { Property(a => a.StreetAddress).HasMaxLength(150); } }
再在OnModelCreating方法中加入
modelBuilder.Configurations.Add(new AddressConfiguration());
书山有路群:452450927
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义