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
|
Hi, just wanting to thank jeremy for taking the time to come & visit the "Tauranga .Net user group", great presentation. Suggestions for LightSpeed: (I'm failry new to LightSpeed so please excuse any that are already implemented)
Thanks for a great product, looking forward to the future. Joel |
|
|
Hi Joel, Great suggestions -- thanks! You can already view and fetch objects marked as deleted by specifying IncludeDeleted = true on your Query object (core API) or by using the IncludeDeleted() operator (LINQ). We'll have a think about undeleting objects -- however, we generally prefer to think of managing deleted objects (whether recovery or purging) as being an admin task outside the scope of LightSpeed, and there are issues around the associations of recovered objects. Generally we would advise that if you want "deleted" objects to remain manageable (e.g. users whose accounts might expire and be reactivated), you should model deletion via a domain property and explicit filtering on this property, rather than relying on soft-delete. We're looking at ways to improve navigation around the design surface and we're thinking about a "mini-map," but we're not sure whether the Visual Studio toolkit we use will support this. We have in recent nightlies added a filter/find feature which will help you to rapidly move to a given entity -- I'll try to put up a blog post on this at some point. We'll take a look at the collection manager idea -- this might help with WPF data binding as well. If you could post your examples then this would be really helpful -- thanks! |
|
|
Re-opening this old post: I have a simple inbox modeled such that items marked deleted show up in a "Trash" folder. The "move back to Inbox" feature is implemented by setting DeletedOn to null. This, uh, "design" is used throughout the app for other features as well. Is there no way to modify the DeletedOn field? I have another, uh, design where I use an int field to specify deleted. It's either NULL or the userid that deleted the object. Then, for completeness, another table with a bit set inside a flags field to indicate deleted. (Hey, this was back when disk space mattered and I was already stuck writing everything as stored procedures. Why not have a little fun?) That last idiotic scenario notwithstanding, perhaps an abstraction over soft delete is up for discussion? |
|
|
I second this. I have here the "I have another, uh, design where I use an int field to specify deleted." problem. I overcome that with a trigger that keeps the "DeletedOn" and "Deleted" field in sync. I needed to create triggers for ~150 tables - sure that is automated right now but it is ugly! I would love to get rid of that. An abstraction on that will be much appreciated! Sörnt |
|
|
Hi, You'll want to take a look at the Audit features of LightSpeed: This will allow you to have LightSpeed track the user who performs functions such as delete. I hope that helps. John-Daniel Trask |
|
|
I think we're looking at it from the opposite direction. I would prefer something like: my existing app already has a BozoLegacyDeleted field. Please use "AND BozoLegacyDeleted != 0" instead of "AND DeletedOn IS NOT NULL" when querying. Edit: I see this blog entry documents just that (http://www.mindscapehq.com/blog/index.php/2012/03/26/ninja-entity-filtering-in-lightspeed) however I'm not sure how to override cleanly. The normal DeletedOn gives me the IncludeDeleted operator. For the "filter on all members who are active" scenario, the login case -- where you'd want to query all members -- falls out cleanly because you get the global flag for free. Other scenarios have me baffled. Also: I assume DeletedOn is readonly for a reason. If I override, will bad things happen if I tinker with it? My use case is simple with no dependencies or cascades. Where are the pain points? |
|
|
We don't currently have a clean way to turn off the filter on a per-query basis. The simplest way to do this right now would be to use a thread static variable. We realise this is very ugly though. We'll have a think about this and see if we can offer a better way. DeletedOn is readonly because it should not normally be modified by applications -- like CreatedOn and UpdatedOn, it's meant to be maintained by LightSpeed at specific points during the entity lifecycle, not arbitrarily updated whenever some random bit of app code wants to. If you make it read-write, it would probably work as long as there are no dependencies or cascades (but note that you could be opening up a future risk if someone later adds an association). It's not part of our test suite though. If you do this, don't forget to use the Set method rather than setting the field directly -- otherwise LightSpeed won't know it's changed and won't have a reason to update the database. |
|
|
The next nightly build will have a Query.IncludeFiltered property and LINQ IncludeFiltered() operator. These work in a similar way to IncludeDeleted but apply to user-defined filters. I initially considered a way of turning off or passing control data to individual filters, but decided that if you wanted to go down to that level of detail you might as well just turn off all filters and write the query explicitly. I am open to feedback on this. |
|
|
Totally reasonable, thank you! Any chance I can get those methods (and IncludeDeleted) on EntityCollection as well? Also to clarify my use case: if I have no cascades and I set DeletedOn = null then do a SaveChanges(true), am I ok? |
|
|
It depends on how the collection is being loaded. EntityCollections are usually properties, so there's no way to pass in a parameter when lazy loading them. (The parent entity doesn't remember the settings of the query which loaded it, and they wouldn't be meaningful anyway because of retrieving entities from the identity map.) For eager loads, however, the IncludeDeleted and IncludedFiltered settings do get applied to any EntityCollections that are eager loaded. So if you're going to need an unfiltered collection, you can use a named aggregate to make it eager load so it picks up the IncludeFiltered setting. Alternatively, when you want an unfiltered collection, you can write an explicit query with the IncludeFiltered option set. |
|
|
I believe so. It's not something we test, but I would expect it to work. The best thing to do really is try it out and see if it behaves the way you want! |
|