それほど単純ではありませんが、DB でテーブルを動的に作成して使用することができます。
まず、テーブルに関するメタデータを保存する必要があります。名前、プロパティ、プロパティの型などです。
EntityTypeConfiguration
次に、これらのテーブルにアクセスするためのエンティティと、次のようなクラスを生成する必要があります。
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class FooTypeConfiguration : EntityTypeConfiguration<Foo>
{
public FooTypeConfiguration()
{
ToTable("Foos");
HasKey(t => t.Id);
Property(t => t.Name).HasMaxLength(200)
.IsRequired();
}
}
の助けを借りて、中間 C# コードなしで DLL を動的に生成できますSystem.Reflection.Emit
。または、C# コードを生成し、それを使用System.CodeDom.Compiler
してコンパイルすることもできます (この方法の方が簡単です)。また、Roslyn コンパイラを試すこともできます (ただし、アドバイスできるほど十分な経験がありません)。
3 番目に、コンパイル済みの DLL をロードしDbContext
、modelBuilder.Configurations.AddFromAssembly(...)
.
アセンブリで必要な型を見つけて、それを使用してデータにアクセスできます。
string typeName = ...;
var type = dynamicLoadedAssembly.GetType(typeName);
var set = dbContext.Set(type); // non-generic DB Set
System.Reflection
またはを使用dynamic
して、これらのオブジェクトを操作できます。最後に、C# コードを生成する場合は、プロパティとインターフェイスの実装を生成して、これらのプロパティに名前でアクセスできます。
public interface IAccessorByName : IReadOnlyDictionary<string, object>
{
object this[string name] { get; set; }
}
public Foo : IAccessorByName
{
private static readonly IDictionary<string, Func<Foo, object>> getters = new Dictionary<string, Func<Foo, object>>
{
{ "Id", (foo) => foo.Id },
{ "Name", (foo) => foo.Name },
};
private static readonly IDictionary<string, Action<Foo, object>> setters = new Dictionary<string, Action<Foo, object>>
{
{ "Id", (foo, value) => { foo.Id = (int)value; } },
{ "Name", (foo, value) => { foo.Name = (string)value; } },
};
public int Id { get; set; }
public string Name { get; set; }
public object this[string name]
{
get { return getters[name](this); }
set { setters[name](this, value); }
}
}
同様のインターフェースを使用して、オブジェクトを動的に作成、読み取り、更新、および削除できます。
string typeName = "Foo";
var fooType = dynamicLoadedAssembly.GetType(typeName);
var foo = (IAccessorByName)Activator.CreateInstance(fooType);
foo["Id"] = 1;
foo["Name"] = "Jon Skeet";
var fooSet = dbContext.Set(fooType);
fooSet.Add(foo);
dbContext.SaveChanges();