StoreGeneratedPattern - Is this supported?
Printed From: IdeaBlade
Category: DevForce
Forum Name: DevForce 2010
Forum Discription: For .NET 4.0
URL: http://www.ideablade.com/forum/forum_posts.asp?TID=1904
Printed Date: 21-Apr-2026 at 12:19pm
Topic: StoreGeneratedPattern - Is this supported?
Posted By: jsobell
Subject: StoreGeneratedPattern - Is this supported?
Date Posted: 21-Jun-2010 at 9:29pm
In one of our EF4 based projects we just hit the old 'StoreGeneratedPattern' bug in VS2010, where it doesn't correctly set the attribute in the SSDL area for columns that have a 'Default Value or Binding' set. However, the EF4 fix/bodge of adding 'StoreGeneratedPattern=Computed' doesn't cut the mustard; the purpose of this field is to specify what should be inserted in this field if no value has been provided.
Ideally we need a new enum in the EF4 set; StoreGeneratedPattern.DefaultValue or something.
So I decided to try the same thing in DF2010...
As an example, I have a table with three columns: Name nvarchar(50) LastEdited DateTime (Default = GetDate()) ts TimeStamp
Now when I generate the edmx, it sets ts to StoreGeneratedPattern=Computed, but ignores LastEdited. However, a simple creation of this entity, set the name, AddEntity, then call SaveChanges complains (unlike EF4) that 'ts' must be supplied. Of course I can supply with with a dummy array of byte[8] which is ignored...
I'm sure I can bodge up the underlying entity through partial classes and property interceptors, but I'm sure this is not the intended method of reflecting the database structure. I was hoping DF would help with the second issue I mention, but we appear to have tripped at the first!
|
Replies:
Posted By: jsobell
Date Posted: 22-Jun-2010 at 4:38pm
|
Ping! Quite important for us!
|
Posted By: ting
Date Posted: 22-Jun-2010 at 9:06pm
|
Yes, as you noticed:
1) The Entity Framework designer has an issue with setting StoreGeneratedPattern=Computed.
2) Even if this setting persisted correctly, it still doesn't give you the behavior you are looking for because it would always overwrite any provided value.
If I read your post correctly, you can accomplish this behavior in DevForce by using the EntityServerSaveInterceptor. There, you can inspect the objects just before saving on the server, and update any audit information about the entity prior to the transaction.
|
Posted By: jsobell
Date Posted: 22-Jun-2010 at 9:31pm
The issue here is that by modifying (or correcting) the attributes in the EDMX file, EF4 is able to cope with these properties in an acceptable manner. EF4 also handles timestamps correctly. These should never be written to the tables, yet DF seems to insist that a value be written.
So the most important issues here seem to be:
- Having to modify the base elements for 200 properties on 50 entities in a database is not sensible.
- There are some behaviors that cannot be performed in the EntityServerSaveInterceptor. For example, if we are using a default of NewSequentialId() in a column, this cannot be generated by C#.
- If the time is different between Server and Website then dangerous situations can arise (such as data marked as being modified later than its deletion date)
I know that even persisting the values correctly in EF is still not ideal, but it is significantly better than the issues above.
Any other suggestions?
|
Posted By: jsobell
Date Posted: 24-Jun-2010 at 6:07pm
A temporary (but slightly dodgy) workaroundfor the TimeStamp properties is as follows. However, I can't see any way of accessing the fact it is specifically a TimeStamp field (this example is assuming all Byte[] fields are timestamps), and it doesn't even touch on the Default problem above. I could have used the field name "ts" for all timestamps, but the ideal would be to know the underlying database type.
public class QsEntitySaveInterceptor : EntityServerSaveInterceptor { protected override bool ValidateSave() { var now = DateTime.Now; var e = base.EntityManager.FindEntities(EntityState.Added).Cast<Entity>().ToList(); foreach(var entity in e) { var timestamps = (entity).EntityAspect.EntityMetadata.EntityProperties.Where(ep => ep.DataType == typeof(byte[])); foreach (var prop in timestamps) prop.PropertyInfo.SetValue(entity, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, null); var createddates = (entity).EntityAspect.EntityMetadata.EntityProperties.Where(ep => ep.Name == "DateCreated" || ep.Name == "LastUpdated"); foreach (var prop in createddates) prop.PropertyInfo.SetValue(entity, now, null); } return base.ValidateSave(); } }
So... interesting questions:
- is there any way to find the database type that underlies an Entity
property?
- is it right that DateTime fields on new Entities are always set to Today? This might be dangerous; forgetting to set it in code might not be detected, and what if we want to know in the Save Interceptor whether a value was entered or not? Might a date of DateTime.Min (or 01-01-1900 for non-DateTime2) not be better?
Also, non-nullable string fields don't have a default of String.Empty, so why are DateTimes set to a value?
- do you know of any way to make the EF4 designer retrieve other SQL metadata such as 'Default Value or Binding'?
- is it possible to influence the SQL of fields that will be inserted on added entities (i.e. remove inserted parameters so defaults are used)?
Ah, so many questions and so little time to answer them all...
|
|