c# – EF,Code First – 如何在insert上设置一个自定义的Guid标
在处理在Guid中作为主键的数据库中插入新的实体时,我面临着以下问题 – 具有代码第一种方法的EF 5.
我知道有很多类似的主题,因为我在这个问题上花了几个小时,但是我不能找到这个问题的主题. 作为一个例子,我的POCO类是: public class EntityRole : IAdminModel { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid Id { get; set; } [Required] [MaxLength(50)] public string Name { get; set; } [Required] [Display(Name = "Role code")] [MaxLength(20)] public string RoleCode { get; set; } [Display(Name = "Entities Assigned")] [InverseProperty("Role")] public List<Entity> Entities { get; set; } } RoleCode和Name只是文本数据,在管理面板中是可编辑的,所以不要考虑这些字段名称. 添加新实体时,我不指定主键值.到目前为止这么好,一切都很好.作为一个主键字段,它需要值并具有自动生成值,所以不应总是指定Id,但是如果我设置了一个值,那么应该保留它(如果启用了identity insert). 但是在某些情况下,我想指定一个主键值,例如用于初始化数据库的值.我需要它来进行后续处理 – 只需说我需要具体的Guid就可以了.所以如果我在我的配置类中: // Initial data seed protected override void Seed(WebPortalDbContext context) { context.MenuItems.AddOrUpdate( m => m.Id,new EntityRole {Id = new Guid("268bf332-910e-4ea1-92f8-1ac0611f4c62"),Name = "Some name",RoleCode = "SN"},); } Guid键设置不起作用,即使我经常添加: using (var context = new MyDBContext()) { context.MenuItems.Add( new Entity() {Id = new Guid("<some guid>"),Name = "fooname" /*some other values*/} ); context.SaveChanges(); } 我在SQL Server跟踪中有: exec sp_executesql N'declare @generated_keys table([Id] uniqueidentifier) insert [dbo].[EntityRoles]([Name],[RoleCode]) output inserted.[Id] into @generated_keys values (@0,@1) select t.[Id] from @generated_keys as g join [dbo].[EntityRoles] as t on g.[Id] = t.[Id] where @@ROWCOUNT > 0',N'@0 nvarchar(50),@1 nvarchar(20)',@0=N'Chief Captain',@1=N'CO1' 这里很明显,新的Guid值不是从EF SQL生成器发送到SQL Server,所以问题在EF中. 所以我删除了DatabaseGeneratedOption.Identity属性,然后它是好的,但我失去了自动生成的Id键,这对我来说不起作用,因为这是非常罕见的情况. 我现在唯一的解决办法是: 我最终是覆盖DBContext的SaveChanges()方法,并修改所有要添加的状态的实体(我从here开始想法): /// <summary> Custom processing when saving entities in changetracker </summary> public override int SaveChanges() { // recommended to explicitly set New Guid for appropriate entities -- http://msdn.microsoft.com/en-us/library/dd283139.aspx foreach (var entry in ChangeTracker.Entries().Where(e => e.State == EntityState.Added)) { var t = entry.Entity.GetType(); if (t.GetProperty("Id") == null) continue; var info = t.GetProperty("Id").GetCustomAttributes(typeof (DatabaseGeneratedAttribute),true).Cast<DatabaseGeneratedAttribute>(); if (!info.Any() || info.Single().DatabaseGeneratedOption != DatabaseGeneratedOption.Identity) { if (t.GetProperty("Id").PropertyType == typeof(Guid) && (Guid)t.GetProperty("Id").GetValue(entry.Entity,null) == Guid.Empty) t.GetProperty("Id").SetValue(entry.Entity,Guid.NewGuid(),null); } } return base.SaveChanges(); } 结合这一点,应该删除所有的DatabaseGeneratedOption.所有型号都具有名为“Id”的主键,遵循命名约定的最佳实践主题之一. 但是这并不是非常优雅的工作,因为我想要EF5应该能够处理这种情况.如果身份插入开启,它适用于Int身份. 有人有什么想法如何在问题上实现更好的解决方案? 解决方法
这是一个简单的方法,因为它是一个GUID,是在你的类中有一个构造函数
public EntityRole() { Id = Guid.NewGuid(); } 并删除数据库生成的选项或将其更改为DatabaseGeneratedOption.None. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |