This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
It sure would be nice to have a way to access the Id of an Entity<> from the base Entity class this would be very usefull in environments where some tables have long Id's and some have GUID Id's perhaps a GetId() abstract method on the base entity that returns an object? |
|
|
We have added an GetId() method to the base Entity class. (It is marked as [EditorBrowsable(Never)] so you may not see it in Intellisense; this has been done to avoid cluttering the API of derived classes.) This will be in nightly builds dated 18 October and above. Please note that nightly builds are now coming from the 2.1 codebase and you may need to update reference paths and strong names accordingly. |
|
|
Thankyou much |
|
|
I am writing an application that will be transfering data between databases in different environments. My plan is to copy property values from the LightSpeed entity to a DTO in one envrionment, serialize it to XML, deserialize in the other, copy the values back to a LightSpeed entity and then save it to the database. I am serializing a DTO rather than the LightSpeed entity because there are strict requirements on schema of the data that gets moved between environments. The issue I have identified is that there is no way to manually set the Id in the destination environment, a GUID, to be the Id value in the first. Could you add a SetId(object id) method to the base Entity class? |
|
|
No, we do not want to add a SetId method to the base Entity class, because this introduces a lot of complexity around the identity map, foreign key fields, updating the database if the entity already has an ID there, etc. What I have done instead is to add a virtual GeneratedId method to the base Entity class. LightSpeed will call this method when it needs to generate an ID -- i.e. it will be called only once per entity, and only for new entities (not those loaded from a database). The default implementation delegates to the identity method on the LightSpeedContext (or entity TableAttribute), but you can override it to supply your own ID. I believe this will address your use case (albeit slightly less conveniently) while avoiding the dangers associated with an arbitrarily callable SetId method. Needless to say, implementations must ensure that generated IDs are (a) of the correct data type (or at least convertible) and (b) unique. This won't be a problem in your scenario though. The Entity.GeneratedId() method will be available in nightly builds dated 11 Nov 2008 and above. |
|
|
That would solve the issue of not being able to specify an Id explicitly but it doesn't seem very user friendly to me. Have you thought about only letting SetId be callable when the Entity is in a new state? |
|
|
Yes, thought about it, rejected it. The basic issue is that we really want the ID to be set only once, and only at the correct time. This is easily enforced by having LightSpeed call a user-provided override instead of its default. It is problematic to enforce if we allow/require client code to call SetId at a time of its choosing. For example, consider the potential contention issue. If the client code happens to look at the Id property before SetId has been called, then LightSpeed will allocate an ID, and then when the client calls SetId we will have to fail it (because the ID has already been set and we don't want to change it). Worse still, looking at the Id property in the debugger results in evaluating the Id property -- so if you looked at the entity in the debugger before calling SetId, you would end up with a different ID, and your SetId call would unexpectedly fail when you stepped through to it. These may not be concerns for you in the replication scenario, but they are very significant concerns in the general case, and I am willing to trade a little convenience for increased safety and predictability. If you want to use the imperative SetId pattern, and given that you can be reasonably confident that your scenario will not realise the potential for weird behaviour, you can easily implement it in a common base class by having SetId stash the ID in a transient field and having GeneratedId consult that transient field. |
|
|
Ok, if the Id being set only once is important then I guess that is the best way. I'll use a base class like you described. |
|
|
Hi, I've overriden the GenerateId() method on some of my entities, to manually set their IDs, because I need to clone some data. Everything is working correctly up to the point where I SaveChanges(). Then, I open the destination database and the IDs are just like there was a sequence key method working. So, the SaveChanges() method must be doing something with IDs because if I look at the entities and relations before calling SaveChanges() everything is just as it should be. I'm using a nightly build I downloaded some 4 hours ago. Thanks for any help given. paulo |
|
|
Can you do something similare for lockversion i.e. add a virtual GeneratedLockVersion method to the base Entity class? This would allow me to set an ID and a LockVersion when i get a entitydto as input to a wcf service. Currently I have to use the following IUnitOfWork.FindOne(id), then check the entity.lockversion with the dto.lockversion. IFF they are the same then then perform a CopyTo from the DTO into this Entity, then save. ELSE throw OptimisticConcurrencyException . (Not to mention the fact I had to edit the VTL templates to add lockversion and id to the DTO objects, it was either that or edit the VTL to generate DTO objects that all inheirited from BaseDTO) It seems very round about and adds an extra DB round trip. Although this DB trip is what I am using to set the id of the entity. AlthoughI can do something dodgy like extend the Entity case with the following. public partial class MyEntity: Entity<int>{ public int? ForceID { get; set; } protected override object GeneratedId(){ if (ForceID == null) return base.GeneratedId(); return ForceID;}
and then change MyEntity.CopyTo to the following public static State CopyTo(this MyEntityDto source, MyEntityentity){ MyEntity entity = new MyEntity();entity.ForceID = source.Id; CopyState(source, entity); return entity;}
Id like to be able to do something similar with LockVersion so I dont have to keep checking the lock version myself, I'd rather let lightspeed deal withit.
|
|