Entity Framework DbSet<?> - Column names of database unknown at compile time - entity-framework

So I have run into a situation where I need to use the Entity Framework (DbContext) with databases whose columns are not known at compile time. Basically I don't have the luxury of hard coding a customTable class to put into the DbSet.
The only thing I can think of for solving this issue is using Reflection.Emit to create a customTable class at run-time based on information I glean by interrogating a database.
I was not able to find any information of solving this issue, but I am very new to working with the Entity Framework so maybe a solution would be more obvious to someone more experienced.
I feel like there should be a cleaner way than using Reflection.Emit to dynamically create a class to feed DbSet.
If I am way off base for the intended use of the Entity Framework that information would be useful as well.

Hi I'm investigating this problem too and I have found what seems like the solution.
http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/
tells you how to make a DbContext into which you add a new DbSet using a type as a parameter. You can create this type using the Dynamic Linq Library:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
It has a method called CreateClass which will allow you to dynamically build a POCO class definition from a list of field names and load it, you can then create a DbSet using the new type you have created.
You can then get a non-generic DbSet from your updated DbContext using
db.Set(type)
where 'type' is a variable holding your new type. This can be worked on using the linq predicates in the dynamic linq library.
Incidentally, my application is for a CMS where new modules can add fields to the core data table for the CMS, and I don't want to use DI as its too inflexible as no given module will be able to provide a type which has all the fields it needs and all the other unknown modules might also need.
James

Related

Dynamic Data Model in Entity Framework Core

I have a database model that can be modify by users at runtime:
adding new columns to existing tables
adding new tables
I want to use Entity Framework Core to access such model.
I'm able of creating the types for the new tables and fields using reflection but I'm not able of creating the DbSet members inside the DbContext class for these new types as the DbSet needs to know the type at compile time.
Does anyone know if this is something that can be achieved with EF Core?
A way of injecting the type to the DbSet member dynamically?
It sounds pretty weird to me that the users are the ones defining the tables and their columns, relationships, etc on runtime. Probably what you actually need is to have a structure of tables to support dynamic data, which is much more manageable, that is, a table that defines the UserModels, another table that defines the properties of those models, etc. That will vary a lot depending on your needs.
You could also consider using some special properties like XML data-type fields as suggested here: Dynamically adding a property to an entity framework object

FSharp Record Types With Entity Framework Code-First

I am doing a proof of concept in a line of business application where I want to swap out the current C# Code-First Entity Framework implementation with a F# one. I am following this article which seems to work pretty well, but I was hoping to use FSharp record types instead of the classes that the article uses. When I try and add a data annotation to a record type like this:
type Family = {[<Key>]Id:int; LastName:string; IsRegistered:bool}
I get the following error:
Error 1 The type 'Key' is not defined
Is there a way to use data annotations with record types? Apparently, EF Code-First needs annotations...
Record types support attributes just fine (and with the syntax you have).
Check if your reference to System.ComponentModel.DataAnnotations is in order, that's where KeyAttribute is defined.
Edit: EF wants to work with properties, that's why using a record doesn't mesh well with EF. You can still make it work in F# 3.0+ by marking the record with CLIMutable attribute (this generates property setters and a parameterless constructor which are taken for granted by C#-centric frameworks and libraries).
The article you're looking at was written with F# 2.0 in mind - CLIMutable wasn't around yet and there was no way of using records for that.

Get Model schema to programmatically create database using a provider that doesn't support CreateDatabase

I'm using the SQLite provider for Entity Framework 5 but it doesn't support CreateDatabase and thus cannot auto create the database. (Code First)
Is there a way I can obtain the Model schema at runtime so that I can create the SQL "CREATE TABLE" command myself?
If not at runtime, some other way to obtain the schema so I know how to create the table properly?
Thanks!
A) As for obtaining the model schema at runtime part
(all are earlier posts of mine)
See this one How I can read EF DbContext metadata programmatically?
And How check by unit test that properties mark as computed in ORM model?
Also this one for a custom initializer Programmatic data transformation in EF5 Code First migration
Having said that...
The problem I see is where and at what point you actually have the data available.
Actually I'm quite sure you won't be able to do that at any time.
Because to be able to extract that info you need to have a DbContext running - so db has to be constructed etc. etc.
In the initializer maybe - but using different ways to get that info - the above is not available.
B)
The other way would be to go the way of implementing a provider, generator etc. (e.g. this post).
That way you should get all that info just at the right time from the EF/CF itself.
However I haven't played with that much.
For more info you can check the EF source code
This is more of a 'gathered info' so far - in case it helps you get anywhere with it. Not really a solution. I'll add some more tomorrow.
EDIT:
To get the real database metadata, look into the other DataSpace, this should get you to the right place...
(note: things tend to get less exact from here - as obviously there isn't the right official support)
var ssSpaceSet = objectContext.MetadataWorkspace.GetItems<EntityContainer>(DataSpace.SSpace).First()
.BaseEntitySets
.First(meta => meta.ElementType.Name == "YourTableName");
If you look up in debugger, Table property should have the real table name.
However, reflection might be required.
How I can read EF DbContext metadata programmatically?
How check by unit test that properties mark as computed in ORM model?
Programmatic data transformation in EF5 Code First migration
Entity Framework MigrationSqlGenerator for SQLite
http://entityframework.codeplex.com/
Entity Framework - Get Table name from the Entity
ef code first: get entity table name without dataannotations
Get Database Table Name from Entity Framework MetaData
http://www.codeproject.com/Articles/350135/Entity-Framework-Get-mapped-table-name-from-an-ent

How to do filtering for many entities of many DataServices in one common class?

Tier database and every single table has a DataSetId and I absolutely want to be sure that the data is always partitioned correctly.
Currently I'm using the QueryInterceptor attribute but it's messy and overly repetitive and prone to errors. Some new Dev could add a new table and forget to filter by DataSetId, or just rename a table. So I've put this in a base class but the IQuerable properties of my repository are never called.
I have a "CoreRepository" class that inherits from ObjectContext, and each of my IQueryable collections uses "CoreObjectSet". CoreObjectSet extends ObjectSet by always adding an expression to filter by DataSetId. When used directly this works fine. But when used for a DataService the Get accessor for the collections on the Repository are never called by the DataService. It appears to be cheating and not using them at all and accessing the data directly.
Is there a way to get the DataService to access through the repository class correctly (And still get the efficiency of passing through the query as SQL)?
If this is the behaviour why even make DataService of T anyway if it's not even going to use the class? For the ADO team to just ignore it and use the edmx directly seems like a hack.
Thanks
Aaron
Looks like the only way around it is to use a T4 template to generate the DataService. I much prefer a base class or some kind of reusable handler but ADO has given me no choice here.

Table per hierarchy inheritance with POCO entities in Entity Framework 4

Our organization is looking to standardize on Entity Framework once v4 comes out. As a result, I am looking at what it would take to migrate our application that uses NHibernate for persistence to EF4 using POCO support. In a couple of places we use single table inheritance (also known as Table Per Hierarchy). I have been unable to get it to work using the following.
Payment (base class [should be abstract but having trouble there as well])
CreditCardPayment (concrete implementation)
ACHPayment (concrete implementation)
CheckPayment (concrete implementation)
Right now, I am mapping them with only the base class properties. All of these classes are in the same namespace. They have a discrimimator that is called PaymentTypeId in the database, so the Payment mapping has a condition of "When PaymentTypeId = 0". Each of the subclasses have the same condition with different values (i.e. CreditCardPayment = 1, etc.).
When I try to load each a list of all payments using DataContext.Payments.ToList() (DataContext inherits from ObjectContext) I am getting the following exception:
"Object mapping could not be found for Type with identity 'DataLayer.DataModel.CreditCardPayment'."
I can't figure out what this means, as the POCO CreditCardPayment class lives in the same namespace as the POCO Payment class does (in fact in the same file).
What am I missing?
This is complaining not about database mapping, but model to CLR mapping.
The EF can't for some reason find your CreditCardPayment class.
Now one possible reason is that you haven't loaded the metadata for it yet.
For example if you have this:
Assembly 1:
- Payment
Assembly 2 references Assembly 1:
- CreditCardPayment extends Payment
Then when you query the EF doesn't know where CreditCardPayment lives.
The way to get around this is with LoadAssembly i.e:
using (DataContext ctx = new DataContext())
{
ctx.MetadataWorkspace.LoadFromAssembly(typeof(CreditCardPayment).Assembly);
// now do your query.
}
You need to tell to LoadFromAssembly every assembly that isn't directly reference by your DataContext class.
Note: typeof(Payment).Assembly is directly referenced because of the IQueryable<Payment> Payments property.
Hope this helps
Alex
Microsoft.
What I didn't represent before (I didn't think it relevant, but it was). Was that CreditCardPayment inherited from an intermediary class named "CreditPayment" and ACHPayment inherited from CashPayment. CreditCardPayment and CashPayment live in the same namespace and file, but were not represented in the EF mapping. Once I added those within the mapping file, everything worked ok.
So, even thought EF does not ever map to one of those types directly, it seems to need to know about them, because it changes the basetype of the CreditCardPayment classes et al. Thank you for your help on this.