Using Both ObjectContext and DbContext - c#

Scenario: Trying to extract and rearange information from one database to an other.
DB A has some data I want to get. I want to store it on DB B in a slightly different structure.
DB A I get using an EDMX database generated model so it uses a derivative of ObjectContext. DB B I would like to be Code generated. So I use the code/model first approach by installing EntityFramework 4.1 via Package manager. So DB B uses a DbContext derivative
When I try to store information from DB A to DB B it's says:
Test method RoutIT.Irma.Import.Service.Test.ImportIrma2ProductTests.ImportProducts threw exception: System.ArgumentException: Could not find the conceptual model type for 'Some entity in DB A's EDMX model'
It actually does it when adding a DB B entity to the DB B's Derived DbContext's DbSet property. So the code is like
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
foreach (FirstPVC pvc in pvcs)
{
this._irmaImport.FirstPVCs.Add(pvc); <--
this._irmaImport.SaveChanges();
}
scope.Complete();
}
}
It happens at the point in the code marked by the arrow above ("<--")
FirstPVC is a DB B property yet at the point of the arrow it complanes about not having a conceptual model for an entity belonging to DB B's context.
This is strange since I try to store an DB B entity to the DB B context. Why should it care about entity's of DB A.
All contexts are contained in the same project. But DB B's Derived DbContext only has knowledge about it's own DbSet<> properties, suddenly when trying to add something to the DbSet<> property it give me the error in bold above.
Anybody know why this happens? Why should DbContext care about entity's of another context specifically one of a ObjectContext derived class.
Perhapse it's usefull to note the entity it's complaining about looks a bit like this
[EdmEntityTypeAttribute(NamespaceName="Irma2Model", Name="AccessProvider")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class AccessProvider : EntityObject
{
/*****...... ******/
}

Found an answer, its not what you want to hear though:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/d2a07542-cb33-48ba-86ed-4fdc70fb3f1a
"If you are using the default code generation for the EDMX file then the generated classes contain a series of attributes to help EF find which class to use for each entity type. EF currently has a restriction that POCO classes can't be loaded from an assembly that contains classes with the EF attributes. (Short answer is no, your classes need to be in separate projects).
This is a somewhat artificial restriction and something that we realize is painful and will try and remove in the future."
So the workaround would be to split the classes into two different assemblies.

Related

How to set default values in Entity Framework 6 (Database First)

Background: I’m beginning a project to convert a web application using Linq2Sql to use Entity Framework (v6) instead. I have a lot of experience with L2S, but I’m brand-new to EF. Since our application and its database already exist, we’re using the “Database First” approach. Also, the database is evolving, so we’re making changes in the schema and the model is updated from the revised database, which regenerates code for the EF model each time.
For many of our entities (database tables), we set default values in our code whenever an entity is constructed. In Linq2Sql it’s easy: define a partial class for the entity, and add a method to the class like this:
partial void OnCreated() { SomeProperty = SomeDefaultValue; }
Whenever Linq2Sql constructs a new entity object, it calls the OnCreated() method you define, and the default values are set as desired. It works great.
The Problem: In EF, I don’t see a way to do this in a Database First scenario.
If I modify the model code generated by EF, the model code is overwritten whenever we update the model after a database revision.
If I define a partial class for the entity in a separate file and define a constructor, the compiler complains that the constructor is already defined.
There doesn’t seem to be any support for something like L2S's OnCreated() method, either.
Any suggestions?
EDIT: Thanks everyone for the helpful comments, but I think I need to point out an important consideration: My goal is to use the database-first approach and stick with it, rather than switching to code-first. When the database schema changes over time I want the EF Designer (or POCO Generator or whatever tools) to update my EF entity classes to match. All without losing my additions to initialize class properties when the class is constructed in the application. This is easy in Linq2Sql, but I just don’t see a way to accomplish this in EF database-first. All suggestions are welcome!
1 . Open .edmx file
2 . Select the field that has the default value and go to the properties
3 . then select StoreGeneratedPattern
4 . then change the value to Computed
i think it's worked.
OP here – I’ve given credit for the answer to ErikEJ but I’d like to recap what I’ve learned on this topic to share with others. There are three goals:
Use the database-first approach and stick with it, even as the database schema is changed over time. That is, have EF produce the code for each database table entity, based on a preexisting database, and update the code when the database is altered.
Provide a mechanism to initialize entity object properties each time the object is constructed, such as Employee.Dependents = 1, for example. (I know simple defaults can be set by the database schema, but more complex initializations must be executed by code.)
The custom initialization code must be preserved when the database schema is altered and EF regenerates the model code.
EF doesn’t provide a way to set properties each time an entity object is constructed in the database-first scenario. Editing the EF-generated code doesn’t work because it gets overwritten whenever EF regenerates the code after a change to the database schema. So far, four workarounds come to mind:
One idea is to add a constructor with more than the default zero-parameter constructor for each entity class. For example, c = new Customer(x) rather than the default c = new Customer(). Application code would call the new constructor, which would inherit the default constructor and add additional code to initialize the class properties. This avoids duplicating the default constructor, something that isn’t permitted by C#. The new constructor is in a separate partial class file, so it will not be overwritten when EF generates updated models from the database.
However, there is a risk that the application programmer may call the default constructor by accident, leading to subtle bugs.
Another solution is to wrap the entity classes in another class, say, a Customer2 class wrapped around the Customer class. The new class would inherit the original class and add initialization code for any properties as needed.
Since these new classes are separate from the original entity class code, they will not be overwritten by EF when it regenerates model code. It may be possible to hide the entity classes from the top-level application code, to avoid accidentally referring to the original classes by accident. If so, this should be a good technique, although I haven’t tested it yet.
A third-party tool, EntityFramework Reverse POCO Generator, is a help. It generates POCO model code much as EF does, but it is not EF. It has an option to generate partial classes, and the entity classes include a InitializePartial() method much like Linq2Sql’s OnCreated(). I think this will work fine for regenerating code as the database is altered over time. My concern here is that this is a third-party product, and there’s always a risk that it can become obsolete or unsupported.
Finally, you can alter the template that EF uses to generate code. The basic idea is to have the generated code add “partial void OnCreated()” to each class, and this lets us use the same convenient technique built into Linq2Sql. I assume newer versions of EF may overwrite the template changes, but it’s just one change in the template rather than changes to every entity class. This method is described here (How to efficiently set default entity values in Entity Framework 6, Database First) and the YouTube video is here (https://www.youtube.com/watch?v=i8J2ipImMuU).
Thanks to all who contributed! I hope this page is helpful to others, so you don’t have to burn as much time as I did looking for a solution.
Use the EF Reverse poco template- it will derive defaults from the database. You can override the InitializePartial method in your partial class to set defaults in code.
Coming from the EF background, I generally do it in the code first migration manually. In the up function of the generated migration, you can do something like this
AddColumn("dbo.Person", "IsActive", c => c.Boolean(nullable: false, defaultValue: true));
AddColumn("dbo.Person", "Name", c => c.String(nullable: false, defaultValue: "Mirza"));
Or to add default SQL value, use
AddColumn("dbo.Person", "CreatedDate",
c => c.String(nullable: false, defaultValueSql: "GETDATE()"));
However there's a downside of this approach in my opinion which is you have to keep a track of your (useless) migrations.
Just found this post looking for an answer to the same issue. Here's a work around that works for me.
Create a partial class for the entity (DB Table) you want to specify default values for, eg:
namespace myApplication.MyModel
{
public partial class myEntityName
{
public myEntityName(bool InitialiseOnConstruct) : this()
{
if (InitialiseOnConstruct)
{
this.property1 = defaultValue1;
this.property2 = defaultValue1;
}
}
}
}
Then in the code, to construct the entity:
thisEntity = new EntityName(true);
OK, it's an extra step, but it works. Hope that helps.

How to access child tables with Entity Framework

I have following tables: Animal and ConcreteAnimal. I am going database first approach if it makes any difference in this example. Suppose they are separate entities. Then I have 2 DBSet(s) generated, and can update separately either of the table. Things change once I set ConcreteAnimal as child of Animal in entity designer. Entity Set field of ConcreteAnimal in entity designer becomes disabled and is automatically populated with the value of entity set of its parent class Animal. DBSet for ConcreteAnimal is not longer generated in the context. This means that I can no longer access the second, child, table. How am I supposed to add ConcreteAnimals to the database? Is it expected behavior? If yes, what is the logic behind it?
EDIT:
OK, I tried following code and it works.
using(var context = new MyEntities())
{
var concreteAnimal = new ConcreteAnimal
{
//setting properties here
//both for Animal and specific to ConcreteAnimal
};
context.Animals.Add(concreteAnimal);
context.SaveChanges();
}
Magic happened, and both tables were populated with correct data. This is good. However, it just does not look logical to me why we have DBSet for base class only?
You are currently using TPT Inheritance.
Common information are saved in the Animal table and specific information from a type in their own table.
You will find information you are looking in these articles:
Table per Hierarchy (TPH)
Table per Type (TPT)
Table per Concrete class (TPC)
Edit
Why we have DBSet for base class only
It's actually a good question, I cannot give an exact answer but from my opinion this is not implemented by default because it's not necessary and would be very confusing.
Just imagine some very complex TPT scenario with a lot of inheritance, they would have one DbSet for every concrete class (which could be easily hundred of additional DbSet), then now you will have to ask to yourself, from which DbSet to do you have to retrieve, add or remove this concrete type.
You can easily add the code yourself once it's generated (in a partial class) and it's will work.
public DbSet<ConcreteAnimal> ConcreteAnimals { get; set; }

Declaring DBSet<Type> within DBcontext - Entity Framework Code First

When using EF Code First to generate a database, you declare the DB sets within the DbContext class for example..
public DbSet< ProductOption > ProductOptions { get; set; }
Now from the reading I have been doing, if you have a related entity in the type ProductOptions you do not need to declare it as EF will look at the dependents and use them to create the required DB tables.
My question is this: Is this recommend practice? And if so how do you then access the related type in code as it does not exist as a data set.
Also this auto-discover feature of EF, does it do it in both directions, i.e if you declare a db set that does not have any related entities inside it, but it is an entity that is in some other entity, will EF find it?
Any clarification is welcome. Thanks
EDIT
Example of what I am saying in terms of not being able to access the Types that are auto discovered is when your seeding data.
You actually do have access to the types without declaring DbSets inside your context class. Inside your context initialization class under the Seed method you can access any of your entities using the yourContext.Set().Add(theObject). This way you do not need to have DBSet properties inside your context class. I am not sure what version of EF you are using or if your are using an initialization class for seeding the data. Regardless, you can still use the .Set().Add, to seed the data.
With regards to the question will EF find the non related entities. Like you said, as long as an object is a property of an entity EF should create a table for it. As long as in code first you declare a mapping for any entity, it should create it and any child entities that may or may not have mappings for themselves. I'd have to see how you are declaring your context and mappings to be sure.

Customize entity materialization in Entity Framework 6

Is there a way to materialize an instance of your own class that derives from the entity type specified in your model? Let's say I have a "ClassName" property in my model for a given entity and whenever EF materializes an instance of the entity, I want to create an instance of the specified ClassName instead (which is a sub-class of the entity of course).
I know there is the ObjectMaterialized event on the ObjectContext but at this point the entity is already created.
var objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
objectContext.ObjectMaterialized += OnObjectMaterialized;
I need a hook right before this to customize the object creation. You might ask why on earth would I need to do this. I have a large object model that changes constantly so I can't define all my classes in the EDMX. The properties that I store in the database can be abstracted to a couple classes at the top of the object model hierarchy. I intend to create entities for those using table-per-type inheritance. But if I could retrieve specific object instances directly when using EF that would be awesome.
Thanks!
I wanted to create custom proxys and debugged deep into the entity framework. I found the translator class, which is responsible to create the entities by reflection. The namespace of the class is System.Data.Entity.Core.Common.Internal.Materialization.
The method creating the entites is the private method Emit_ConstructEntity. The entity type is a parameter and is created by the private method LookupObjectMapping based on an EdmType object (I was using model first).
If you want to change the class, which are created, you have to create a custom MetaDataWorkspace. The workspace is responsible to select the EdmType. Maybe try to debug into the methods yourself and have a look how the MetaDataWorkspace is used to identify the CLR type.

Can I have 2 different EntityFramework contexts share a single SqlServer Compact database?

I have a SqlServer Compact Edition database that contains 2 tables.
For each of these tables, I have a context class derived from DbContext which is used by the application to access the table.
In order to keep the different components of the application decoupled, I can't have one context class that would have DbSet properties for both of the tables. Rather, I need to have 2 different context class, each of them has to be completely unaware of the other and its data.
I'm using the code-first approach, my code defines the entities and model, and I let Entity Framework create the database for me.
My problem is: how can I still let Entity Framework create the database and the tables for me automatically on context initialization, but still have the 2 contexts share the same database and connection?
Right now what I get is, the first context successfully creates the database and the table in it, but when I try to create the second context, I am getting, unsurprisingly the following error:
The model backing the 'SomeObjectContext' context has changed since the database
was created. Either manually delete/update the database, or call Database.SetInitializer
with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges
strategy will automatically delete and recreate the database, and optionally seed it with
new data.
None of the available IDatabaseInitializer are appropriate for me, because I don't want the entire database to be dropped when the second context is created. I just want the second context's table to be created in the existing database.
Any advise on how to solve this would be appreciated.
Thanks
You can't use CodeFirst this way with only one database. CodeFirst has to check the model classes against the db structure to work properly (they have to be "in sync").
In order to keep the different components of the application
decoupled, I can't have one context class that would have DbSet
properties for both of the tables. Rather, I need to have 2 different
context class, each of them has to be completely unaware of the other
and its data.
If booth tables have no connections to each other and its a requirement for your application to have these tables completely separated, why don't you create two databases and have a context for each of them?
At all, I would go with one database, have an internal DbContext and two different public repository classes which encapsulate the access to the two tables. If all your code is within the same assembly, you can access your internal context from your repository class. Someone who needs access to the repository may access the repository for the table he needs to.
Yes, you can use multiple DB context pointed to same DB.
Arthur Vickers from Entity Framework team recommends the following pattern….
Instead of specifying separate connection strings in your app.config file for multiple context, just set one string and give it a generic name.
<connectionStrings>
<add name="MyDBContext" connectionString="Your conn string here" providerName="System.Data.SqlClient" />
</connectionStrings>
Then create a base context class that will use the connection string:
using System.Data.Entity;
namespace DataLayer
{
public class BaseContext<TContext> : DbContext where TContext : DbContext
{
static BaseContext()
{
Database.SetInitializer<TContext>(null);
}
protected BaseContext()
: base("name=MyDBContext")
{
}
}
}
Now, inherit this base behavior in each context (for instance):
namespace DataLayer.Models
{
public class OrderContext : BaseContext<OrderContext>
…
namespace DataLayer.Models
{
public class ProductContext : BaseContext<ProductContext>
…

Categories