2

is it possible to dynamically build entities in entity framework 6 using code first?

is it also possible to add properties to those entities at runtime?

Can those entities reference each other using foreign keys?

If someone could point me in the right direction if this is possible, i would really appreicate it.

EDIT

i have changed the title to reflect more of what i would like, so u can see why i asked the questions i asked.

Basically i would like to create a system where a user can define the objects(tables) they want, with the properties on that object (columns in table) as well as the references to each object (relationships between tables).

Now each object would have an Id property/column. i was thinking of atoring these definitions in an eav like table structure but i have other ibjects that are defined at design time and i like to use linq queries on these objects. I would also like to be able to build linq queries on these objects as users will want to report on this data. Building the linq queries should be fine as could use dynamic linq for this (Maybe)?

Currently to create such a system i have created a table that has many text fields, many number fields, many relationship fields and users can use which ones they want. But this is just 1 table and i think this is going to bite me in the bottom in the end, thus why i would like to take it to the next level and build separate tables for each object.

if anyone knows of a better way or maybe experienced something similar, glad to hear opinions.

Gillardo
  • 9,518
  • 18
  • 73
  • 141
  • What actual scenario you are trying to target with this question? – Wiktor Zychla Apr 25 '15 at 21:09
  • Are you intending to create new tables using EF at runtime? – Felype Apr 25 '15 at 21:09
  • Could you rephrase your question to include what it is that you are trying to achieve and how you think "dynamic EF entities" are going to help you solve that. Right now this sounds very much like an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Alex Apr 25 '15 at 21:22
  • rephrased with little explaination – Gillardo Apr 27 '15 at 13:16

4 Answers4

1

Ive been interested in this topic since ef4. Have a real world solution that could use it. I dont...

Rowan Miller is one of the EF developers. He wrote a blog on this topic. Dynamic Model creation Blog Explaining how you might do it.

A github example buybackoff/Ractor.CLR see OnCreating Showing how.

It would appear ok, but has a many practical restrictions that make a recompile with generated code or hand code more practical.

It is also why i have not down voted others. :-)

Would it be fun watching someone dig their own grave with a teaspoon?

Consider the runtime implications.

  1. These approach still rely on the POCO type discovery. the an assembly can be generated from code on the fly. And then there is SO POCO and runtime

  2. During context creation the initializer runs. You adjust the model. The auto migrate then adds the news properties and tables. So during that period of time NO other contexts can be instantiated. Only non EF access possible during the automatic migration. So you still have a logical outage.

    1. You are now using previously unknown pocos, in unknown tables. What repository pattern are you using...

eg I used this type of pattern....

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;
}

and cast this against IRepository after making a dynamic call to the factory. But i was unable to avoid dynamic calls. Sticky situation.

good luck....

Edit / After thought I read a blog about ef 7 There are some very interesting comments from Rowan about potentially not needing CLR types. That makes the dynamic game a bunch easier. You could try the ef7 beta if brave.

Community
  • 1
  • 1
phil soady
  • 11,043
  • 5
  • 50
  • 95
1

You can create an EF model dynamically using reflection:

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);
}
Bohdan
  • 1,987
  • 16
  • 23
0

it possible to dynamically build entities

The short answer is no, one cannot dynamically build new or existing entities once EF has defined them during design time.

is it also possible to add properties to those entities at runtime

But that does not mean one has to live with those entities as they are... To achieve a dynamism one can extend the entities via Partial class to the entity. Then one can have any number of new properties/methods which could achieve what the runtime aspect which possibly you are looking for past a generated entity.

Can those entities reference each other using foreign keys?

Not really, but it is not clear what you mean.

If the entity was generated in design time and during runtime a new FK constraint was added to the database, then an entity could be saved if it does not know about the FK, but if the FK requires a value then the process of saving would fail. Extraction from the database would not fail.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
0
  • Q: is it possible to dynamically build entities in entity framework 6 using code first?
    A: No

  • Q: is it also possible to add properties to those entities at runtime?
    A:No

  • Q: Can those entities reference each other using foreign keys?
    A: Unless you've defined the entity beforehand, no.

Maybe you've confused things with what's called CodeFirst, where you write your domain / business models in C#, define their relationships with other entities, and then generate a database based on your C# models...

Here's an overly simplistic example that you can get started with if that's what you're trying to achieve.

First make sure you have EntitiyFramework installed... you can get it from NuGet...

pm> Install-Package EntityFramework

Then copy the code below to your project

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());
    }
}

Once you've done that... Open the package manager console and type in the following commands...

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

And you should then have your database generated for you from that

Aydin
  • 15,016
  • 4
  • 32
  • 42