私はthis answerのアイデアに基づいて列挙型リストを実装しようとしています。私の目標は、ドメイン内でEnumを使用できるようにし、データベースから保存して取得するときにクラスインスタンスに変換させることです。それは(以下ソース)であるようなコードを使用しエンティティフレームワークの列挙型リストを模倣し、最初にコードを使用してDDD
は、私は、メッセージにDbUpdateException
を得る:PRIMARY KEY制約の
違反 'PK_dbo.Faculty'。オブジェクト 'dbo.Faculty'に重複キーを挿入できません。重複キー値は(0)です。 ステートメントが終了しました。
私はFacultyのすべてのインスタンスを新しくしているので、期待しています。
それを修正するには、私がいない成功を収めて few questions on this、 から解決策を試してみました。彼らはエンティティを添付するか、その状態をUnchangedに設定することを提案しました。だから私はSaveChanges()
と使用を上書きしようとした:
ChangeTracker.Entries<Faculty>().ToList().ForEach(x => x.State = EntityState.Unchanged);
と
ChangeTracker.Entries<Faculty>().ToList()
.ForEach(x => Entry(x.Entity).State = EntityState.Unchanged);
とさえ
ChangeTracker.Entries<Department>().ToList().ForEach(department =>
{
foreach (var faculty in department.Entity.Faculties)
{
Entry(faculty).State = EntityState.Unchanged;
}
});
しかし、それらのすべてがメッセージをInvalidOperationException
を投げる:
追加情報:Sa 'TestEnum.Entities.Faculty'タイプの複数のエンティティが同じ主キー値を持つため、変更を受け入れることができませんでした。明示的に設定された主キー値が一意であることを確認します。データベース生成の主キーがデータベースとEntity Frameworkモデルで正しく構成されていることを確認します。 Entity Designerをデータベースファースト/モデルファースト構成に使用します。コードファースト構成のための「HasDatabaseGeneratedOption」流暢なAPIや 『DatabaseGeneratedAttribute』を使用してください。
どのようにデータベースにこれらを試してみて、挿入しないためにEFを指示することができますか?私は、次のよと私はSaveChanges()
内で動作するように、この実装を必要とします。次のようにDDD設計ルールとドメインロジックから分離保つインフラ
コードは次のとおりです。
class Program
{
static void Main(string[] args)
{
using (var dbContext = new MyContext())
{
var example = new Department();
example.AddFaculty(FacultyEnum.Eng);
example.AddFaculty(FacultyEnum.Math);
dbContext.Department.Add(example);
var example2 = new Department();
example2.AddFaculty(FacultyEnum.Math);
dbContext.Department.Add(example2);
dbContext.SaveChanges();
var exampleFromDb1 = dbContext.Department.Find(1);
var exampleFromDb2 = dbContext.Department.Find(2);
}
}
}
public enum FacultyEnum
{
[Description("English")]
Eng,
[Description("Mathematics")]
Math,
[Description("Economy")]
Eco,
}
public class Department
{
public int Id { get; set; }
public virtual ICollection<Faculty> Faculties { get; set; }
public Department()
{
Faculties = new List<Faculty>();
}
public void AddFaculty(FacultyEnum faculty)
{
Faculties.Add(faculty);
}
}
public class Faculty
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
private Faculty(FacultyEnum @enum)
{
Id = (int)@enum;
Name = @enum.ToString();
Description = @enum.GetEnumDescription();
}
protected Faculty() { } //For EF
public static implicit operator Faculty(FacultyEnum @enum) => new Faculty(@enum);
public static implicit operator FacultyEnum(Faculty faculty) => (FacultyEnum)faculty.Id;
}
public class MyContext : DbContext
{
public DbSet<Department> Department { get; set; }
public DbSet<Faculty> Faculty { get; set; }
public MyContext()
: base(nameOrConnectionString: GetConnectionString())
{
Database.SetInitializer(new MyDbInitializer());
}
public int SaveSeed()
{
return base.SaveChanges();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
modelBuilder.Properties<string>()
.Configure(p => p.HasMaxLength(100));
modelBuilder.Configurations.Add(new DepartmentConfiguration());
modelBuilder.Configurations.Add(new FacultyConfiguration());
base.OnModelCreating(modelBuilder);
}
private static string GetConnectionString()
{
return @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TestEnum;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;MultipleActiveResultSets=true;";
}
}
public class MyDbInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(MyContext context)
{
context.Faculty.SeedEnumValues<Faculty, FacultyEnum>(@enum => @enum);
context.SaveSeed();
}
}
public class DepartmentConfiguration : EntityTypeConfiguration<Department>
{
public DepartmentConfiguration()
{
HasMany(x => x.Faculties)
.WithMany();
}
}
public class FacultyConfiguration : EntityTypeConfiguration<Faculty>
{
public FacultyConfiguration()
{
Property(x => x.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
}
public static class Extensions
{
public static string GetEnumDescription<TEnum>(this TEnum item)
=> item.GetType()
.GetField(item.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.FirstOrDefault()?.Description ?? string.Empty;
public static void SeedEnumValues<T, TEnum>(this IDbSet<T> dbSet, Func<TEnum, T> converter)
where T : class => Enum.GetValues(typeof(TEnum))
.Cast<object>()
.Select(value => converter((TEnum)value))
.ToList()
.ForEach(instance => dbSet.AddOrUpdate(instance));
}