views:

2559

answers:

5

I have a database that I wish to build an EF model from, however I do not want to include certain columns from the database as the columns concerned are maintained exclusively on the server and should not be manipulated by any application.

Both of the columns are DateTime (if this makes any difference), one of the columns is nullable and is maintained by a trigger on updates and the other is not nullable and set using a default value in the table definition.

I guess I am looking for something like the "Server Generated" option in Linq2Sql; but I cannot find such an option.

Can anybody tell me how to work around this?

Caveat:

I have been trying to introduce business object modelling at my place of work for some years and it has always been rejected because of the amount of additional code that has to be hand-cranked. EF is currently being seen as a viable solution because of the designer and code generation therefore any option that involves hand-cranking the XML will only turn the rest of my colleagues away from EF. I am therefore looking for something that can be done either using the designer or using code.

EDIT:

I guess that what I am looking for here is either...

(a) a way to create the model without EF referencing the columns in the store (ssdl) and therefore not looking to manipulate it in any way (b) a way to programatically set the "StoreGeneratedPattern" attribute against the property when I create the ObjectContext (the easy answer is to manually manipulate this in the .ssdl, but this would then be overwritten if I refreshed the model from the database and I cannot go down the route where the .csdl, .msl & .ssdl are hand-cranked).

A: 

Do you not want the column to appear in the model at all?

Try selecting the column in the Designer view and hitting the delete key.

Edit

You could make the setter for the property private. Then your app won't be able to modify the value.

TGnat
Unfortunately, if I try this I then get errors in the model as the column is not mapped.
What kind of errors?
TGnat
Error 3023: Problem in Mapping Fragment starting at line 197: Column TableName.ColumnName in table TableName must be mapped: It has no default value and is not nullable.
The problem with manipulating the setter is that the model still knows the column exists and therefore tries to pass the default value for the type on an insert - for the DateTime this is a value outside of the SQL Server range and overrides the default value anyway.
A: 

Can you not create a view with the columns you need and import it through entity function wizard and map it to your entities?

CodeToGlory
Thanks, this could be a solution though I would prefer to avoid having to create a view for every table if I can - the columns I have described in my original problem actually appear on every table in the database.
+1  A: 

Right click on the field in the graphical representation and choose delete. Ive found that sometimes you will get errors when you make a lot of changes to the modeling at once and start to lose track of your changes. Your best bet might be to rebuild the EF generated model.

Keep in mind that when you "update from the database", that old fields on the generated models will not be removed, you will have to remove them manually. For example if you renamed DateField1 to DateField2 in your database, and then you "Update Model from Database", you will now see both DateField1 and DateField2 on the resultant model. This can be a cause of errors.

This works on the column that is nullable, but does not work for the column that is not nullable, producing the same error as the option above from TGnat.
Error 3023: Problem in Mapping Fragment starting at line 197: Column TableName.ColumnName in table TableName must be mapped: It has no default value and is not nullable.
I got ya...I think you may be stuck. Interesting note though...i have a rowversion (timestamp) column on one of my db tables, and the EF generator correctly set the StoreGeneratedPattern attribute: <Property Name="RowVer" Type="timestamp" Nullable="false" StoreGeneratedPattern="Computed" />
Interesting; I wonder what is different with the TimeStamp column to make it do that?
+2  A: 

Can you do this with the Entity Framework? Yes; it's easy. Can you do this with the Entity Framework designer? Unfortunately, that is much harder.

The problem you're having is that the column exists in the storage schema (SSDL) in your EDMX. Removing the column with the GUI designer simply removes it from the client schema, not the mapping or the storage schema. However, it's simple enough to go into the EDMX and remove it. Having done that, you can also remove it from the mapping in the client schema portions of the EDMX, and the entity framework will longer complain that it is unmapped.

Problem solved, right?

Well, no. When you use the GUI designer to update the EDMX from the database, the storage schema is thrown away and re-generated. So your column will come back. As far as I know, there is no way to tell the GUI designer to never map a particular column. So you will have to re-do this every time you update with the GUI designer. Fortunately, the EDMX is XML, so you can do this with a XML transform, LINQ, or the XML tool of your choice.

Craig Stuntz
Thanks, I kind of realised that I could do this by editing the XML, I was just hoping there was another way - such as programatically setting the StoreGeneratedPattern attribute when creating the context.
Well, the answer is the same (for StoreGeneratedPattern). You can set StoreGeneratedPattern in the XML and it will work fine, but the GUI designer will blow it away when you update. The Entity Framework has features that the GUI designer doesn't completely support yet.
Craig Stuntz
The only other option is to try and change your database metadata such that the GUI designer recognizes what you want. But I don't know how the GUI designer generates SSDL in the specific case of StoreGeneratedPattern.
Craig Stuntz
A: 

Timestamp is a different data type than DateTime. Timestamp seems to be recognized as an attribute the engine manages, much like an identity attribute. You can't "update" a timestamp attribute. Hence, the EDM can manage it correctly (just as it does an identity).

silverfox1948