Entity Framework, Inheritance and Namespacing - entity-framework

I am using the Entity Framework 4.0 and have a conceptual model that makes heavy use of inheritance.
I can perform the standard inheritance functionality just fine but I am having trouble with the namespacing of the generated C# classes.
My problem is that the Entity Framework always generates all the classes (both base and derived) in the same C# namespace. A hypothetical example of the fully qualified names of the classes generated by the Entity Framework (both base and derived) with a root namespace of "MyApp" would look like the following
MyApp.MyBaseClass
MyApp.MyDerivedClassA
MyApp.MyDerivedClassB
MyApp.MyDerivedClassC
etc...
However, I want to to put the base and derived classes into different namespaces. For example, the base class would still be defined in the root namespace (eg. MyApp) but the derived classes would be defined in a "sub namespace" (eg. MyApp.MyDerivedClasses). The fully qualified names of the derived classes would then look like the following:
MyApp.MyDerivedClasses.MyDerivedClassA
MyApp.MyDerivedClasses.MyDerivedClassB
MyApp.MyDerivedClasses.MyDerivedClassC
etc...
I managed to achieve this with Linq To Sql by manually creating (ie. not using the Linq To Sql Designer) InheritanceMappingAttribute on the base class and pointing the mapping to the derived classes that are defined in the "derived" namespace.
However, I can not figure out if it is possible to use different namespaces between the base and derived classes with the Entity Framework 4.0 (with or without the designer). Can this be done and if so how can I do it?

No it is not possible using the standard set of tools.
The namespace specification on the designer file applies to all entities contained in it.
You could try a code first approach to get around this (prolly your best option). Other than that get a good book on T4 templates and modify the T4 POCO generator to let you specify these things.

Related

Entity Framework Class Naming Conventions v Old School Database Naming Conventions

I am looking at using some kind of Data Generation technology for my next project and was curious about the ADO.NET Entity Framework using Visual Studio 2010. I am new to the entity framework so please be gentle.
My preference for class naming has always been camel case. For example CustomerSite.
My preference for database naming has always been lowercase with underscores. For example customer_site. This seems to be the norm over the last decade where I have worked with database administrators from many companies which is why I adopted this technique.
Using the entity framework to generate my classes, it always uses the table name, so my class name becomes customer_site. Which I hate.
I am mid-coding through a prototype, where the database has many tables (say around 40). At present, I have been working on my own Data Model, but I am sick of hand-coding fields and properties. It is a VB.NET WinForm application with standard CRUD for entities with vareious bells and whistles on top.
Is it possible to make the entity framework class generator use the naming convention of what I want or not? Or do I need to change my database naming conventions? Or just go with what the entity framework class generator gives me - customer_site as class name.
Any thoughts?
Thanks,
Andez
As mentioned in this question, you can set up mapping between your entities and your tables which enables you to have different table and class names. You can do this by overriding DbContext.OnModelCreating, or by using the TableAttribute.
I'd say if you're comfortable doing it you should stick to different naming conventions for your tables and entities.

Change MyEntityFrameworkModel.edmx.cs File

I was wondering if can change the edmx.cs file (change inheritance and base constructors of object context derived class).
when I try this , all changes will defect as i build the project.
Note I mean changing the object context derived class not entity classes.
thank you.
If you can afford it (meaning if your project is not too complex already), I could suggest that you switch to code-first style (EF 4.1). That allows you to build all the inheritance you want in your objects. And since you create your own context by inheriting DbContext, you also have total flexibility there.
You can use your EDMX (with the T4 template packed in EF 4.1) or your existing database to create the classes (so at least what you have done until today still stands).
http://thedatafarm.com/blog/data-access/quick-look-at-reverse-engineer-db-into-code-first-classes/
http://devlinliles.com/post/Reverse-Engineer-Code-Firste28093Jump-start-for-existing-Databases.aspx
The partial class solution would maybe do it too (depending on what you wish to achieve).
To change in entity frame work class its better to create Shared classes with same name and add your own methods and properties

Poco+Entity Framework 4. Where should I add my methods for working with Poco classes?

I've tried to use Entity Framework 4 and POCO for my MVC 3 project. May be, I don't understand the main idea of this ORM, but the problem is following:
I added ADO .NET Entity Data Model and make model according to database.
I clicked Add Code Generation Item and added ADO .NET POCO Entity Generator.
It makes classes for every database table.
I want to add some methods to work with data (Add, Update, Delete, GetAll etc) to appropriate models.
For LINQTOSQL I added partial classes and placed them to Models. But now I can't do it because:
a) Models folder has classes with the same names, which was created by POCO.
b) If I place my partial class in the another folder, it will be another namespace - so, such classes won't be partial one.
c) If I place my code in POCO classes, it can be destroyed during update POCO.
How can I use it? Where sould I place my methods for data working?
Is the best way to make for POCO and EF the other project - http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx?
First of all you don't have to write your CRUD inside POCO,
There are many places where you can do it like in edmx.cs file or write one more layer which is called as CRUD Services which handles the Database operations using context object.
Now coming to your questions,
Create separate Models folder and place the Model classes in there.
Your Model class may like this,
EmployeeDepartmentModel
{
prop EmpList List(Emp);
prop DeptList List(Dept);
//Emp and Dept are my POCOs
}
So now I have to fill both of these list(Your CRUD question),
For that, I will Create one method in Controller class(its better to write such logic in some another library, but for time being I suggest you to create in Controller),
FillTheModel()
{
EmployeeDepartmentModel.EmpList = EDMX.GetAllEmployees;
EmployeeDepartmentModel.DeptList = EDMX.GetAllDepartments;
}
Now you can bind this model with your view.
You can place the partial classes in another folder and modify the namespace.
I agree with allisewell, but if you really want to add parts to partial classes, give files another name,
e.g. MyPoco.Part2.cs or modify t4 template to name generated files
e.g. Poco.Generated.cs

Entity Framework Bottom-up Inheritance

I use standard ObjectContext and EntityObjects in my application. Let's say two of my tables are Projects & Services. Projects have Subproject (from Projects table with ParentID == ProjectID) and also Services. So I would have a hierarchy like Projects->Subprojects->Services. But I need to inherit Projects and Services from an abstract base class so I can use any of these entities as a new Task/Job entity in my application. Then, for example I can create a TreeList listing all Tasks (either a Project or Service). Is there anyway in EDMX designer I can create a new type (entity) which is the base calss for two or more concrete types?
It is possible with TPC inheritance but it will include a lot of complication to your design. For example:
you will have to move shared properties to the base class
you will probably have to maintain some mappings manually in EDMX (at least I had when I did the sample on screenshot)
you will have only single ObjectSet<Tasks> and you will have to use OfType to query only Projects or Services
you will have to use unique Id per Task = across both Project and Service tables (can be achieved by correctly configured identities in database)
It will look like:
Another option is using interface on your entity objects instead of parent class. You can define interface in your partial part of entity object and handle retrieving both Projects and Services by yourselves where your UI will expect only list of types implementing your interface.
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/01/25/table-per-concrete-type-inheritance-in-entity-framework.aspx
Since it sounds like your data is coming from 2 separate tables, Projects and Services, no, I don't think you can achieve this in the designer (at least, not without hand-editing the generated edmx). If there were a common table to represent the base class, that could be done in the designer, but that doesn't sound like it fits your situation.
What you may be able to do is use an interface instead of an abstract base class, and use partial classes in your entity model to implement the interface for each of your entities. You can't directly inherit from your abstract base class in your entity model, because all of your entities already derive from EntityObject. If you have a lot of shared implementation that resides in your base class, it might be worthwhile to switch to POCO, where you can define your own inheritance hierarchy.

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.