I have two databases, Sales and Production. For a certain set of tables, the schema is exactly the same. I generated two contexts using the Database First method. I specified a different namespace for both.
However, the designer doesn't actually wrap the classes in SalesStore.Context.vb in a namespace. And when I add it manually, of course it gets lost the next time I make a change to the model.
And so I am getting a bunch of errors: 'multiple definitions with identical signatures'.
How can I change the model so that the namespace is attributed properly to the generated table classes?
TIA,
Miles
Use code-first from an existing database workflow. This will allow you to stich together the generated models and share entity types between DbContexts. It's a little bit of work, but once you ditch the EF designer, you'll never miss it.
Related
I am working on redesigning a database for a product called Project Billing. I am having trouble coming up with table names. In the old database, the names were super obscure (PRB_PROJ_LVL), so old is of no help. The database is small - 10 tables or so - but will grow over time.
Here's the problem - Projects are an entity (and table), but the word is also used as an adjetive. Example
Project - a table containing projects.
ProjectTask - a table containing project tasks; this is a child of Projects.
ProjectTemplate - a table for project templates, which is not a child of Projects. Project templates just serve as a model for creating a bunch of ProjectTasks.
So, how do I show that ProjectTask is a child of Project but ProjectTemplate isn't? Thanks as always.
Internal documentation of your schema and its intended use is one of the better ways to do this. Relying on naming convention alone will always leave open the possibility for interpretation - explicit definitions don't do that. That said, we have defined some objects which are intended for use as models (templates in your case). These model objects are not to be used or directly manipulated by the production application and over time are mutable with new objects being based on modified models. One way we tried to apply self-descriptiveness was the introduction of schema. Since we had different departments that could make use of the same model objects, we had something along the lines of (adjusted to apply to your question without assuming too much):
[dept_X].[projects]
[dept_X].[project_tasks]
And for templates, which are never directly used by the application or users (per say):
[model].[projects]
[model].[project_tasks]
As a programming reference for our developers, schema definition scripts contain documentation describing object relationships (as do the objects internally do via foreign keys, etc). As an added measure, a wiki article is generated for all new objects sorted by project. Objects existing prior to this new system (my onboarding) get documented as they get modified or as time permits which ever comes first.
I'm looking into using Microsoft's Entity Framework in an upcoming project which is a point release of an existing product. Our current product supports two DBMS (Oracle and SQL Server), the schema of each is maintained in separate .sql script files.
The entity framework (4.1) looks appealing because it allows various scenarios to be implemented automatically via code generation, reflection, etc. However, as far as I can tell, some of these benefits appear to be mutually exclusive of others.
For example, to support multiple DMBSes, I am inferring that I would need to use a model or code first design, in which case EF would generate the schema for each according to the model (I have seen little to no posts or documentation on this, so I may be wrong). This means that our existing schema would need to be either abandoned (model-first), or mapped (code-first). Additionally, updating the schema would require manual scripts as EF does not appear to support schema upgrades (without wiping out data).
Are model-first and code-first the only viable means of supporting multiple DBMSes in EF? I realize that technically it would be impossible to guarantee that two arbitrary schemae are the same, so I am thinking this is true.
Are there any potential pitfalls of code-first and mapping to multiple DBMS systems? For example, Oracle does not have auto-increment columns; you have to use sequences. How is this mapped in the DbContext? Do I need to create separate maps for each DBMS?
Does EF support any mechanism to upgrade an existing DBMS schema to one of which is representative of the EF model (schema recreation =/= upgrade), or am I limited to doing this manually?
I did come up with one possible way to use database first and support multiple DBMSes, however it is a maintenance nightmare. The idea was to add another layer of abstraction to the two generated data models and create converter classes for each of the EF generated models. This seems like the best way of doing it so that each DBMS could potentially have its own model, yet my code would handle the mapping. But in doing this, what am I really gaining from EF? Maybe query generation, but is that worth it?
Actually both the model-first and the database-first have same constraints. Both these approaches are using an EDMX file which contains SSDL (a description of store = a database layer) part related directly to a single database provider so if you want to have two different database providers you must have two different SSDL parts and keep them in sync. You can use single CSDL (a description of conceptual layer = your model classes) and a single or two MSLs (a description of mapping between SSDL and CSDL - a single file is possible only if tables and columns will have exactly same names in both SSDLs). As I know EDMX file can consists only from single SSDL, CSDL and MSL parts so I expect that the designer has no support for this scenario and you will have to modify second SSDL manually or use two EDMXs = model each change twice.
The code-first approach can make this much more simple but the question is how good is Oracle provider when using the code-first and the database generation. The provider is responsible for correctly interpreting needed features like sequences in case of auto increment columns.
EF itself currently has no support for upgrading existing DB. When using EDMX the process of the database generation is controlled either by T4 template or Workflow so it can be customized and there is already separate feature called Entity Designer Database Generation Power Pack which allow incremental building of the database with the model-first approach. The problem is that this feature is using VS Database tools. I think these tools works only with SQL server. I never like these automated tools so I still think that database upgrade should be controlled manually with help of some tools to get difference script between the current and the last deployed database versions. You should need diff script only when deploying new the new version to a production environment. In a testing and a development environment you can always recreate the whole database.
There should be no abstraction needed when working with two EDMX models. Models must produce the same conceptual layer. In such case you need only a single set of POCO classes which are mapped by conventions (same class name as the entity, same properties with same types and accesibility) so they will work with both models.
Edit:
Based on #Tridus answer I'm just adding that you can create databases first and use fluentAPI from EF 4.1 to map them. Your databases must have exactly the same schema (table names, column names, etc.), they can't use any specific features (I hope sequences will not be the problem because it is just the way how Oracle handles auto increment columns).
This is actually fairly doable with a database first design, but there's some caveats you won't be able to get around easily due to how the databases handle things differently.
Sequences are one (in that they're just ignored by EF entirely). You can fake that in Oracle by putting a trigger on the table that populates it on Insert, but I also found that if you have to update the model later then EF "forgets" that the column is an identity column and it'll try to stick a 0 in it again. I also found it unreliable in Oracle to try and get the new ID if you use a trigger. We just wound up selecting from the sequence and setting the ID on the object before doing the insert because that's how you usually do it in Oracle. You could also use a stored procedure that handles it.
Numbers aren't handled the same way. SQL Server uses number formats that map to Int32, Int64, etc. Oracle's number format is totally different and a full range Int32 in SQL Server is a Number(10,0) in Oracle... which is actually an Int64 in EF because it's bigger then an Int32. I also found that Oracle's EF provider likes to use Decimal a lot even when it doesn't have to, but that's probably just a beta issue.
Stored Procedures in Oracle require some values to be put in app.config/web.config in order to work in EF. I'm not sure if that's going to just be clutter in SQL Server or if it'll cause problems.
Finally, EF Code First is pretty immature and according to the docs doesn't support changing the database structure in this version. I'm not sure if Oracle's provider supports it either (it might, haven't tried it).
Most of this is stuff you can get around, but you're going to need to do some work to hide the differences from the rest of your code and it'll probably take a wrapper layer to do it.
edit - In regards to your #4 - EF 4.1 can generate partial POCO classes. Instead of writing a wrapper around each of the generated models to hide any differences, you can create another partial class code file that won't be regenerated when you update the model, and then add properties/methods that hide the differences. Your app code would just have to be aware to use those instead, and they'd handle the issue (like the number issue I mentioned, you could completely hide it with another property that can do the necessary casting for Oracle).
I got a legacy database which have about 10 identical tables (only name differs).
Is it possible to be able to use the same business entity for all tables without having to create several classes/mapping files?
You can use the entity-name feature if you are using NHibernate v2.1 or higher. It is poorly documented but I am actively using the feature. It has gotten hard to find the documentation on it but look here:
Section 5.3 in
http://docs.jboss.org/hibernate/core/3.2/reference/en/html/mapping.html#mapping-entityname
A couple of things to be aware of. You must now use entity-name instead of class name to refer to the objects. In general it is not an entirely transparent change moving from class names to entity names.
Session actions now require two parameters, for example:
_session.Save("MyEntity", myobject)
The entity-name controls what table the data goes into.
Some HQL queries do not work right anymore, sometimes you must use Criteria instead.
If you need a set of sample code I may be able post some, but far too busy at the moment. I suggest you look at the limited info you can find and set it up for a very simple object and multiple tables to learn how it all works. It does work.
You can create a base class with all the properties, but you still need to map them all.
For that, you can either use copy&paste, XML entities (see examle at http://nhibernate.info/doc/nh/en/index.html#inheritance-tableperconcreate-polymorphism), or a code-based mapping method (Fluent or ConfORM). They usually make reuse easier.
One thing that bothers me about nHibernate is that it is not 100% compile time tested.
If I rename a column in my database table, and I update the mapping file for that table, when I hit compile I should get errors in all my query code (hql/criteria whatever) of where I referenced that column name and how it is spelled wrong.
The whole point (for me anyway) of using an ORM was that database changes won't break my queries.
In other words, I will be notified at compile time of what needs to be fixed, instead of getting runtime errors etc.
To achieve what you want I think your best solution is to use a combination of Fluent NHibernate and nhlambdaextensions. Fluent NHibernate will give you type-safe checking on your mapping files (so if you change a property on your entity, the compiler will throw an error if you don't also change the property on your mapping class). The lambda function extensions will give you type-safe queries via the Criteria API (not HQL since that's just magic-strings SQL-with-objects).
Also to clarify your question, you said:
If I change a column (rename) in my
database table, and I update the
mapping file for that table, when I
hit compile I should get errors in all
my query code (hql/criteria whatever)
of where I referenced that column name
and how it is spelled wrong.
Just changing the database side should break nothing (assuming you also make the change in your XML mapping file). Your code does not reference the column="first_name" portion of the mapping, it references the name="FirstName" portion. If you do not change your entity, renaming a column (from "firstname" to "first_name", for example) in the database will not break your queries as long as you update your mapping file as well.
You should look at Castle ActiveRecord. I used this before and it allows you to not worry about the mapping files (.hml) as much. It lets you make your changes at the class level definitions, and the mappings files were generally untouched.
If you are writing bad queries, that sounds like a design problem, not an nHibernate problem.
You won't get errors providing the Property names haven't changed, as most people use HQL for their queries in NHibernate.However if you do change the Property names and not the HQL you will indeed get broken queries, e.g.:
FROM User Where User.Surname = 'bob'
Change the Surname property to Lastname and it'll break. It's a feature lacking in NHibernate but would make a good project for the contrib - a Subsonic style query interface. This a project sort of similar but still use HQL.
As mentioned above ActiveRecord and Fluent NHibernate are the closest to type checking with NHibernate. Both enforce that you inherit your classes from their base class, as you'd expect and ActiveRecord is not intended for production use - Ayende has said in a video that's meant to be a prototyping tool for NHibernate.
Hibernate uses dynamic byte code generation to create the mapping classes, based on the mapping configurations.
The fundamental point of ORM is to enable auto-magical mapping (bridge) between Objects and Relational systems. Thus: ORM.
if you want to strongly type your objects rather than using xml config which can cause alot of runtime issues if not properly tested, I would look into FluentNHibernate which has convention maps that allow you to map your classes to data in code. Made my life alot easier especially when first starting with NHibernate wish i had found it before i knew how to properly map using xml
Does NHibernate have the equivalent of the Java version's schema validator? In which case, you could add a step to your build process to build the session factory and run the validator-- building the session factory should also compile named queries, hence validating them too.
Hmm, looks like it supports something like that: http://nhibernate.info/blog/2008/11/22/nhibernate-schemavalidator.html
NB this means your build process will fail to work if your dev database is not available--- which I would regard as a bad thing.
I'm trying to figure the best strategy about how to organize DataContexts. The typical DB we work has between 50 and 100 tables usually in third-normal form and with many relations between them. I think we have two options:
Put all tables in a single context. This will ensure that anything we do will be committed in the correct order in database. The problem is that the LINQ designer will be a mess with 50+ tables and I'm worrying performance may be affected.
Create several data contexts based on the logical grouping of tables. The problem is that there will be places where one side of a relation will be in one context and the other in another one. We'll have to manually take care of committing both context-s in the correct order.
Is there any recommended practice to handle this?
More details:
I want to create my own entities and unit of work on top of LINQ to SQL. Entities will be defined in a xml model file where the mapping to LINQ entities will be specified also. A custom tool will generate my entities (POCO) based on the model. The client code will interact only with my entities and my unit of work; never directly with the DataContext or LINQ entities. However I do not want to duplicate what LINQ to SQL provide out of box so I want to use the underlying LINQ DataContext. This means that I cannot have two orders in different data contexts, because it wouldn't be possible to map my POCO Order with both of them.
This is a common question that has been thoroughly analyzed here: http://craftycode.wordpress.com/2010/07/19/linq-to-sql-single-data-context-or-multiple/
In essence, you should create at most one data context per strongly connected group of tables, or one data context per database.
LINQ-to-SQL mappings are like typed DataSets, in that when you use one, you're dealing with a session containing data. You can have the same tables in several different DataContexts. They're only classes, after all; they don't mean anything until you start interacting with the database, by filling them with existing data or using them to create new data.
So perhaps you have Customer, Address, Phone, etc. tables that you deal with when you're sending out a new catalog. Then you have Invoice, Line Item, Product, etc. tables that you use when you're creating an order. But in that latter set you may want to have Customer as well. That's fine. You should just take care to only have one session active at a time so that you're not using inconsistent data. You shouldn't have problems from overlapping entities in your various DataContexts as long as you're not using them in an overlapping way.
As far as the clutter, you can put your DataContext in a specific namespace, and you can also put your various entities in a specific namespace (albeit only one namespace per set of entities in a DataContext). You can do this in the Properties window. This will let you keep the Intellisense less jumbled.
You should create contexts that allow you to perform units of work. This may involve overlapping table mappings.
Context1 : Customer has many Invoices
Context2 : Customer has many Orders
Context3 : Invoice has many Orders
I use one datacontext per database.
Average tables can be up to 100, however from experience I don't experience any performance issues.
The datacontext is in a separate project, which is compiled. The resultant dll referenced from the BLL