博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何为EntityFramework添加Unique功能?
阅读量:6413 次
发布时间:2019-06-23

本文共 5690 字,大约阅读时间需要 18 分钟。

直到目前为止,EntityFramework似乎没有UniqueAttribute这个属性,因而也就无法为数据模型表某个特定字段指定是Unique。那么怎么办呢?我们就DIY一次吧!

首先自己写一个特性,该特性只能被用于property上,由于只是一个标记特性而以,因此类体为空——

[C#]

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]    public class UniqueKeyAttribute : Attribute    {    }

[VB.NET]

_Public Class UniqueKeyAttribute Inherits AttributeEnd Class

然后自己实现IDatabaseInitializer接口。那是因为EntityFramework的DataBase有一个静态方法叫做SetInitialize<T>,其中“T”是预备生成的模型类(继承DbContext),而这个方法需要一个实现该接口的类用于初始化数据库。该类实现如下:

[C#]

public class MyDbGenerator
: IDatabaseInitializer
where T : DbContext { public void InitializeDatabase(T context) { context.Database.Delete(); context.Database.Create(); //获取全部父类的公开属性
var fatherPropertyNames = typeof(DbContext).GetProperties().Select(pi => pi.Name).ToList();                //先剔除由父类继承的公共属性
foreach (PropertyInfo item in typeof(T).GetProperties().Where(p => fatherPropertyNames.IndexOf(p.Name) < 0).Select(p => p))                {                    //获取子类DbSet
中的那个"T"
Type entityModelType = item.PropertyType.GetGenericArguments()[0];                    //反射“T”,并且获取已经加上“Unique”的自定义属性字段名称
var allfieldNames = from prop in entityModelType.GetProperties()                                        where prop.GetCustomAttributes(typeof(UniqueKeyAttribute), true).Count() > 0                                        select prop.Name;                    //逐个开始用SQL命令生成唯一字段
foreach (string s in allfieldNames)                    {                        context.Database.ExecuteSqlCommand("alter table " + entityModelType.Name + " add unique(" + s + ")");                    }                }                           }    }

[VB.NET]

Public Class MyDbGenerator(Of T As DbContext)    Implements IDatabaseInitializer(Of T)    Public Sub InitializeDatabase(context As T)        context.Database.Delete()        context.Database.Create()        '获取全部父类的公开属性                        Dim fatherPropertyNames = GetType(DbContext).GetProperties().[Select](Function(pi) pi.Name).ToList()        '先剔除由父类继承的公共属性                        For Each item As PropertyInfo In GetType(T).GetProperties().Where(Function(p) fatherPropertyNames.IndexOf(p.Name) < 0).[Select](Function(p) p)            '获取子类DbSet
中的那个"T" Dim entityModelType As Type = item.PropertyType.GetGenericArguments()(0) '反射“T”,并且获取已经加上“Unique”的自定义属性字段名称 Dim allfieldNames = From prop In entityModelType.GetProperties() Where prop.GetCustomAttributes(GetType(UniqueKeyAttribute), True).Count() > 0prop.Name '逐个开始用SQL命令生成唯一字段 For Each s As String In allfieldNames context.Database.ExecuteSqlCommand("alter table " + entityModelType.Name & " add unique(" & s & ")") Next Next End SubEnd Class

下面给出测试:

[C#]

public class Category    {        [Key]        public int Id { get; set; }        [UniqueKey]        public int IdentifyCode { get; set; }        public string Name { get; set; }    }    public class DbG : DbContext    {        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            modelBuilder.Conventions.Remove
(); } public DbSet
Categories { get; set; } } public class MainTest { static void Main(string[] args) { Database.SetInitializer
(new MyDbGenerator
()); using (DbG g = new DbG()) { g.Categories.Add(new Category { Id = 1, Name = "Category" }); g.SaveChanges(); Console.WriteLine("OK"); } } }

[VB.NET]

copy to clipboard | view source | convert again Public Class Category    
_ Public Property Id() As Integer Get Return m_Id End Get Set m_Id = Value End Set End Property Private m_Id As Integer
_ Public Property IdentifyCode() As Integer Get Return m_IdentifyCode End Get Set m_IdentifyCode = Value End Set End Property Private m_IdentifyCode As Integer Public Property Name() As String Get Return m_Name End Get Set m_Name = Value End Set End Property Private m_Name As StringEnd ClassPublic Class DbG Inherits DbContext Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder) modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)() End Sub Public Property Categories() As DbSet(Of Category) Get Return m_Categories End Get Set m_Categories = Value End Set End Property Private m_Categories As DbSet(Of Category)End ClassPublic Class MainTest Private Shared Sub Main(args As String()) Database.SetInitializer(Of DbG)(New MyDbGenerator(Of DbG)()) Using g As New DbG() g.Categories.Add(New Category() With { _ Key .Id = 1, _ Key .Name = "Category" _ }) g.SaveChanges() Console.WriteLine("OK") End Using End SubEnd Class

注意:此处的“OnModelCreating”方法必须被重写。因为默认情况下Code-First生成的数据表名总是“实体模型名”(复数)形式,而我的代码目前只考虑了(直接根据模型名)生成表(也就是Add unique这部分)。因此必须取消表的“自动复数化”形式。除了我的这个方法以外,其实还可以采用在模型类上冠以“Table("表名称")”的形式。

测试代码是成功的,不过有时会出现表无法删除的情况,望大伙儿可以指教一二,谢谢!

如果有其它想法或者意见,也请及时反馈,谢谢!

转载于:https://www.cnblogs.com/ServiceboyNew/archive/2012/07/06/2579519.html

你可能感兴趣的文章
chromedriver@2.X.X install: `node install.js` 问题
查看>>
Android 来去电自动录音 (三)
查看>>
rpmbuild
查看>>
网络中均分负载流量
查看>>
OpenStack封装Windows镜像之Installing Cloudbase-Init
查看>>
Spring-基于Spring自定义标签
查看>>
Centos+iptables+l7-filter 封QQ MSN和P2P
查看>>
Code First Migrations 更新数据库结构(EF数据迁移)
查看>>
Linux 的启动流程http://www.ruanyifeng.com/blog/2013/08/linux_boot_process.html
查看>>
关于 NTP 的一些问题
查看>>
领域驱动设计实战—基于DDDLite的权限管理OpenAuth.net
查看>>
去掉tomcat配置文件中的注释选项
查看>>
JavaScript—数组(17)
查看>>
工信部:云计算将成新一代信息技术发展重点
查看>>
配置SCCM 2012 SP1(六)发布应用程序
查看>>
《safe+》离线密码更安全,一键修改最方便
查看>>
正则表达式简明参考
查看>>
两数组最小距离问题
查看>>
DB2各版本下载地址
查看>>
老李秘技:loadrunner回放脚本错误提示Error: "HTTP Status-Code 500"
查看>>