【问题标题】:allowing a user to define a table at runtime using entity framework允许用户在运行时使用实体框架定义表
【发布时间】:2015-04-27 03:29:21
【问题描述】:

是否可以先使用代码在实体框架 6 中动态构建实体?

是否也可以在运行时向这些实体添加属性?

这些实体可以使用外键相互引用吗?

如果可能的话,如果有人能指出我正确的方向,我会非常感激。

编辑

我已更改标题以反映更多我想要的内容,因此您可以了解我问这些问题的原因。

基本上我想创建一个系统,用户可以在其中定义他们想要的对象(表),该对象的属性(表中的列)以及对每个对象的引用(表之间的关系)。

现在每个对象都有一个 Id 属性/列。我正在考虑在类似 eav 的表结构中处理这些定义,但我有其他在设计时定义的对象,我喜欢对这些对象使用 linq 查询。我还希望能够在这些对象上构建 linq 查询,因为用户希望报告这些数据。构建 linq 查询应该没问题,因为可以为此使用动态 linq(也许)?

目前,为了创建这样一个系统,我创建了一个包含许多文本字段、许多数字字段、许多关系字段的表,用户可以使用他们想要的那些。但这只是一张桌子,我认为这最终会咬我一口,因此我想将它提升到一个新的水平并为每个对象构建单独的表格。

如果有人知道更好的方法或经历过类似的事情,很高兴听到意见。

【问题讨论】:

  • 您试图针对这个问题的实际场景是什么?
  • 您是否打算在运行时使用 EF 创建新表?
  • 您能否重新表述您的问题,以包括您想要实现的目标以及您认为“动态 EF 实体”将如何帮助您解决该问题。现在这听起来很像XY problem
  • 改写了一点解释

标签: c# .net entity-framework entity-framework-6


【解决方案1】:

我从 ef4 开始就对这个话题感兴趣。 有一个可以使用它的现实世界的解决方案。 我不...

Rowan Miller 是 EF 开发人员之一。他写了一篇关于这个主题的博客。 Dynamic Model creation Blog 解释你可能会怎么做。

一个 github 示例 buybackoff/Ractor.CLR see OnCreating 展示如何。

看起来不错,但有许多实际限制 用生成的代码或手工代码重新编译更实用。

这也是我没有投票给其他人的原因。 :-)

看着有人用茶匙挖自己的坟墓会很有趣吗?

考虑运行时影响。

  1. 这些方法仍然依赖于 POCO 类型发现。 可以从动态代码生成程序集。 然后是SO POCO and runtime

  2. 在上下文创建期间,初始化程序运行。你调整模型。 然后自动迁移添加新闻属性和表格。 所以在那段时间里没有其他的上下文可以被实例化。 在自动迁移期间只能进行非 EF 访问。 所以你仍然有一个逻辑中断。

    1. 您现在在未知表中使用以前未知的 pocos。 您使用的是什么存储库模式...

例如,我使用了这种类型的模式....

private IRepositoryBase<TPoco> InstantiateRepository(BaseDbContext context, Type repType, params Type[] args) {
   Type repGenericType = repType.MakeGenericType(args);
   object repInstance = Activator.CreateInstance(repGenericType, context);
   return (IRepositoryBase<TPoco>)repInstance;
}

并在对工厂进行动态调用后将其转换为 IRepository。 但我无法避免动态调用。棘手的情况。

祝你好运……

编辑/考虑后 我读了a blog about ef 7 来自 Rowan 的一些非常有趣的 cmets 关于可能不需要 CLR 类型。这使得动态游戏更容易。 如果你有勇气,你可以试试 ef7 beta。

【讨论】:

    【解决方案2】:

    您可以使用反射动态创建 EF 模型:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var entityMethod = typeof(DbModelBuilder).GetMethod("Entity");
    
        foreach (Type type in ...)
        {
            entityMethod.MakeGenericMethod(type)
                .Invoke(modelBuilder, new object[] { });
        }
        base.OnModelCreating(modelBuilder);
    }
    

    【讨论】:

      【解决方案3】:

      可以动态构建实体

      简短的回答是否定的,一旦 EF 在设计时定义了新实体或现有实体,就无法动态构建它们。

      是否也可以在运行时向这些实体添加属性

      但这并不意味着人们必须与这些实体一起生活......为了实现动态,可以通过Partial 类将实体扩展到实体。然后,您可以拥有任意数量的新属性/方法,这些新属性/方法可以实现您在生成的实体之后可能正在寻找的运行时方面。

      这些实体可以使用外键相互引用吗?

      不是真的,但不清楚你的意思。

      如果实体是在设计时生成的,并且在运行时向数据库添加了一个新的 FK 约束,那么如果实体不知道 FK,则可以保存它,但如果 FK 需要一个值,那么保存会失败。从数据库中提取不会失败。

      【讨论】:

        【解决方案4】:
        • Q:是否可以在 实体框架 6 使用代码优先?
          A:否

        • :是否也可以在运行时向这些实体添加属性?
          :否

        • :这些实体可以使用外键相互引用吗?
          :除非您事先定义了实体,否则不能。

        也许您已经将一些事情与所谓的 CodeFirst 混淆了,您在其中使用 C# 编写您的域/业务模型,定义它们与其他实体的关系,然后根据您的 C# 模型生成一个数据库...

        这是一个过于简单化的例子,如果你想达到这个目标,你可以开始。

        首先确保您已安装 EntitiyFramework...您可以从 NuGet 获取它...

        pm> Install-Package EntityFramework
        

        然后将下面的代码复制到你的项目中

        public class User
        {
            public User()
            {
                this.Id = Guid.NewGuid().ToString();
            }
        
            public string Id { get; set; }
            public string Name { get; set; }
            public virtual ICollection<Post> Posts {get;set;}
        }
        
        public class Post
        {
            public Post()
            {
                this.Id = Guid.NewGuid().ToString();
            }
        
            public string Id { get; set; }  
            public string UserId { get; set; }
            public virtual User Author {get;set;}
            public string Title { get; set; }
            public string Body { get; set; }
        } 
        
        public class UserConfiguration : EntityTypeConfiguration<User>
        {
            public UserConfiguration()
            {
                this.ToTable("Users");
                this.HasKey(user => user.Id);
                this.Property(user => user.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
                this.Property(user => user.Name).IsRequired();
        
                this.HasMany(user => user.Posts).WithRequired(post => post.Author).HasForeignKey(post => post.UserId);
            }
        }
        public class PostConfiguration : EntityTypeConfiguration<Post>
        {
            public PostConfiguration()
            {
                this.ToTable("Posts");
                this.HasKey(post => post.Id);
                this.Property(post => post.Id).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
                this.Property(post => post.UserId).IsRequired();
                this.Property(post => post.Title).IsRequired();
                this.Property(post => post.Body).IsRequired();
        
                this.HasRequired(post => post.Author).WithMany(user => user.Posts).HasForeignKey(post => post.UserId);
            }
        }
        
        public class ExampleContext : DbContext
        {
            public ExampleContext() : base("DefaultConnection") 
                        // Ensure you have a connection string in App.config / Web.Config 
                        // named DefaultConnection with a connection string
            {
            }
        
            public DbSet<Post> Posts { get; set; }
            public DbSet<User> Users { get; set; }
        
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new PostConfiguration());
                modelBuilder.Configurations.Add(new UserConfiguration());
            }
        }
        

        完成后...打开包管理器控制台并输入以下命令...

        pm> Enable-Migrations
        pm> Add-Migration InitialMigration
        pm> Update-Database
        

        然后您应该从中为您生成数据库

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-02-09
          • 2022-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-03
          相关资源
          最近更新 更多