[英]Entity Framework Core Auto Generated guid
有人可以指導我primeryKey
我想要一個表的primeryKey
作為guid
,在插入時有db生成的值。
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
但它給出了error
無法添加實體類型“用戶”的種子實體,因為沒有為所需的屬性“Id”提供值。
這是我的實際模型類和 DbContxt 類:
public class BaseModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime? UpdatedOn { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime LastAccessed { get; set; }
}
public class User : BaseModel
{
[Required]
[MinLength(3)]
public string Name { get; set; }
[Required]
[MinLength(3)]
[EmailAddress]
public string Email { get; set; }
[Required]
[MinLength(6)]
public string Password { get; set; }
}
然后在 MyDbContext 中:
public class MyDbContext: DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder mb)
{
base.OnModelCreating(mb);
mb.Entity<User>().HasData(
new User() { Email = "Mubeen@gmail.com", Name = "Mubeen", Password = "123123" },
new User() { Email = "Tahir@gmail.com", Name = "Tahir", Password = "321321" },
new User() { Email = "Cheema@gmail.com", Name = "Cheema", Password = "123321" }
);
}
public DbSet<User> User { get; set; }
}
請任何幫助!
您遇到的問題並非特定於自動生成的 Guid。 任何自動生成的鍵值都會發生同樣的情況,包括常用的自動增量(標識)列。
這是由特定的 數據播種( HasData
) 要求引起的:
這種類型的種子數據由遷移管理,需要在不連接數據庫的情況下生成用於更新數據庫中已有數據的腳本。 這施加了一些限制:
- 即使通常由數據庫生成,也需要指定主鍵值。 它將用於檢測遷移之間的數據更改。
- 如果主鍵以任何方式更改,則先前播種的數據將被刪除。
請注意第一個項目符號。 因此,對於普通的 CRUD,您的 PK 將自動生成,您需要在使用HasData
fluent API 時指定它,並且該值必須是常量(不更改),因此您不能使用Guid.NewGuid()
。 因此,您需要生成多個 Guid,獲取它們的字符串表示形式並使用以下內容:
mb.Entity<User>().HasData(
new User() { Id = new Guid("pre generated value 1"), ... },
new User() { Id = new Guid("pre generated value 2"), ... },
new User() { Id = new Guid("pre generated value 3"), ... }
);
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
GUID 字段適用於 Entity Framework 6.x,可能還沒有在 EF Core 中!
所以解決辦法是:
1)首先編寫您的BaseModel
類,如下所示:
public class BaseModel
{
[Key]
public Guid Id { get; set; }
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedOn { get; set; }
public DateTime LastAccessed { get; set; }
}
2) 那么你的DbContext
OnModelCreating()
方法應該如下:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<YourEntity>().Property(x => x.Id).HasDefaultValueSql("NEWID()");
modelBuilder.Entity<User>().HasData(
new User() { Id = Guid.NewGuid(), Email = "Mubeen@gmail.com", Name = "Mubeen", Password = "123123" },
new User() { Id = Guid.NewGuid(), Email = "Tahir@gmail.com", Name = "Tahir", Password = "321321" },
new User() { Id = Guid.NewGuid(), Email = "Cheema@gmail.com", Name = "Cheema", Password = "123321" }
);
}
現在創建一個全新的遷移並相應地更新數據庫。 希望你的問題能得到解決!
您可以在 Code First 遷移文件中使用defaultValueSql: "newid()"
。
例如;
public override void Up()
{
CreateTable(
"dbo.ExampleTable",
c => new
{
Id = c.Guid(nullable: false, identity: true, defaultValueSql: "newid()"),
RowGuid = c.Guid(nullable: false, defaultValueSql: "newid()"),
})
.PrimaryKey(t => t.Id);
}
除了手動更新遷移,您還可以在 OnModelCreating 中實現一個更新,為您將其添加到遷移中,例如
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// guid identities
foreach (var entity in modelBuilder.Model.GetEntityTypes()
.Where(t =>
t.ClrType.GetProperties()
.Any(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(DatabaseGeneratedAttribute)))))
{
foreach (var property in entity.ClrType.GetProperties()
.Where(p => p.PropertyType == typeof(Guid) && p.CustomAttributes.Any(a => a.AttributeType == typeof(DatabaseGeneratedAttribute))))
{
modelBuilder
.Entity(entity.ClrType)
.Property(property.Name)
.HasDefaultValueSql("newsequentialid()");
}
}
}
GUID
由Identity framework
而不是 EF 處理,因此要使用 GUID,您需要執行以下操作
[Key]
public Guid Id { get; set; }
然后在插入表之前准備模型
new User() { Id = Guid.NewGuid(), Email = "Mubeen@gmail.com", Name = "Mubeen", Password = "123123" },
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id").HasMaxLength(36)
.ValueGeneratedOnAdd();
});
namespace Microsoft.EntityFrameworkCore
{
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
public static class ModelBuilderExtensions
{
public static void SetDefaultValuesTableName(this ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes().Where(x => x.ClrType.GetCustomAttribute(typeof(TableAttribute)) != null))
{
var entityClass = entity.ClrType;
foreach (var property in entityClass.GetProperties().Where(p => (p.PropertyType == typeof(DateTime) || p.PropertyType == typeof(Guid)) && p.CustomAttributes.Any(a => a.AttributeType == typeof(DatabaseGeneratedAttribute))))
{
var defaultValueSql = "GetDate()";
if (property.PropertyType == typeof(Guid))
{
defaultValueSql = "newsequentialid()";
}
modelBuilder.Entity(entityClass).Property(property.Name).HasDefaultValueSql(defaultValueSql);
}
}
}
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.SetDefaultValuesTableName();
}
如果您只需要在創建和保存新實體時獲取自動值,您也可以在構造函數中執行此操作:
public class BaseModel
{
public BaseModel()
{
Id = new Guid();
}
[Key]
public Guid Id { get; set; }
public DateTime CreatedOn { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedOn { get; set; }
public DateTime LastAccessed { get; set; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.