Going for broke and need input

I was recently involved in a discussion at another forum (the DDD community) and have come to some rather humbling realizations about what I really want from my efforts and how affected I am by chosen technologies.

I sat down and came up with a list of things I want, why I want them, and how the technologies I am familiar with fit into things. From this point on, I am unconcerned with patterns and methodologies, how much or little work the result will incur, or whether or not the result is anemic or rich. I just want something that can accomodate my requirements. However, I am unsure whether or not something exists that will do that. I am hoping that by listing these here, one of you will know of something.

On to the list:

  1. Must be able to change an entity parent by it’s foreign key, by reference, or by manipulating the parent’s collections.

The reason I need this is because there are times when a viewmodel provides me with a parent id via a dropdownlist and I simply feel it’s going around your elbow to get to your thumb by selecting the parent and then assigning that, when you already have the id. Just assign that and save. However, I also need the references in order to ease the pain of building navigational display elements.

  • Linq2Sql can do all three, but is limited to SqlServer. Not acceptable.

  • EF4 can do all three, but if a foreign key already has a value, it throws an error. Not acceptable.

  • NHibernate doesn’t allow both a reference and it’s foreign key in the same entity. Not acceptable.

  1. Must be able to selectively apply updates on specific entities without automatically saving all changes made to all manifested entities.

The reason I need this is because there are times when several entities may be in a state of edit, and batched saved. Those that pass internal test should be able to make it through the save process, leaving the ones that failed the test unsaved.

  • Linq2Sql apply all pending changes on SubmitChanges(). Not acceptable.

  • EF4 also applies all pending changes on SaveChanges(). Not acceptable.

  • NHibernate works correctly in this regard.

This is it. Those two simple things would free me up so much it isn’t funny. So are there any persistence engines out there that comply with the list? Or is there some trick to any of the three that I am unaware of, that might make them work for me?

Note: While I am aware that what I am trying to do is NOT considered good practice, it is, nevertheless, what I wish to do. I just need to figure out a way to do it.

You have a valid point. I really don’t like having that property on the entity to begin with. Depth isn’t much better in that regard, but at least it’s not calculated each time. Let me run a scenario by you and see if it is not a better solution.

Originally, I’d intended to duplicate some of the admin screens for the forum system I previously used. In that, they had a list of all forums on one page, indented by parent. One could add, edit or delete from there.

Quite possible the best solution would be to have it list only unparented (top level) forums on the first page and add a detail option. On that detail page, along with the actual detalis, list any child forums in the same manner as on the first page. In this way, indentions become moot. The downside is is that one may have to navigate down more often to reach the forum they want to edit.

What do you think?

If you note my example, I’m searching on the Id for a related object.

Not entirely sure why you have such a problem accessing your object like this.


var threads = from t in Session.Linq<Thread>()
                      where t.Parent.Id == 123
                      select t;

Not sure if it’s your impression that the above would translate in to


select blah, blah, blah from Thread where ParentId in (select * from parent where Id = 123)

NHibernate does not do this (unless you specifically specify this sort of behavior via DetachedCriteria), it will simply issue something along the lines of


select blah, blah, blah from Thread where ParentId = 123

Hey Al, could you elighten me a bit more on something? One of the things I listed was the ability to have both parent and foreign key in the entity. In your response you seemed to indicate that NH can do this, where I thought it could not. Can you explain how to accomplish this?

Sample…

public class Thread : Entity
{
public virtual int ParentId { get; set; }
public virtual Forum Parent { get; set; }
}

In my experience, NH disallows this because it tries to make two associations. If there is a way around this, I’d love to know.

Mate, I’ve posted in some of your other threads and NH will do all those things, however if you want to reference another related object do so by it’s ID.

You can do this in any number of ways, HQL, Linq2NH, CriteriaAPI etc

i.e if you want to do that in Linq2NH, simply do this


var customers = from c in Session.Linq<Customer>()
                      where c.Organisation.Id == 123
                      select c;

If you’re assigning a parent entity to a child. chances are that your parents has already been loaded and unless the object is stale or has changed, NH will simply load it from it’s cache when you attempt to load it from it’s Id.

Even though some of these things may seem “wrong” or like they’d be massive performance issues, don’t let the concern you right now, you can easily tweak how your entities are mapped and how your caches are set up, let alone DB indexes.

I’ve been programming for 8 years now and have used NH commercially for almost half that time and have never found an issue with tweaking performance issues and have never encountered a system I built running NH that couldn’t be tweaked to a degree where the application would scale.

The best advice I can give you is this, stick with one technology and learn it, build your application and refactor where needed and don’t try to come up with the perfect solution upfront, or you will spend an eternity trying to perfect something that has never worked as opposed to perfecting something that IS working. Once it’s working you will quickly see where things are lacking and pin point the areas that could be better.

Al, and others, I am going to make a new thread shortly, please refer to that one for my response.

Again, don’t let your UI drive your domain.

If there is a requirement is to have associated/linked forums then that’s a requirement, how you display that is a secondary concern.

Indented lists, searchable flat structures, display in a tree structure, etc are all UI elements. How you implement them should be a secondary concern.

Get your domain done, get it persisting and THEN make small modifications to either your repositories and/or domain if your UI is really hindered by the domain.

Al

My first question would be, why on earth would you be creating something such as this within your domain!?

The domain should have nothing to do with your presentation layer and the indent is purely for display.

Secondly, why would you calculate this every time? Seems like such a waste and pointless thing to do…

If Parent had a Depth attribute which is populated when it’s created, the new child would simply be Parent.Depth + 1

The presence of the Id isn’t for querying.
scenario one)

// set the id from the model, gotten via drop down
entity.ForumId = model.ForumId;
// now save. nice and simple. no other entities needed.

scenario two)

// additional property on an entity
public virtual string IndentedTitle
{
get
{
int count = 0;
var parent = Parent;
while (parent != null)
{
count++;
parent = parent.Parent;
}
return string.Format(“{0} {1}”, new String(‘-’, count * 2), Title).Trim();
}
}
// needed in views for DisplayFor(x => x.IndentedTitle);

Produces output like:
Item A
– Item 1
– Item 2
----Sub Item
Item B
etc

So it is actually required that I have both. See?

Only thing I can suggest is taking a look at PLINQO. It is linq to sql that supports any database. But you must have the latest CodeSmith, you could also use the trial version.

Thanks for the concise answer there Stalker.

I took a peek and it looks interesting, though I don’t qualify for the free component that it requires.

And I have a correction to make. On further testing, it appears that EF4 does not, in fact, error out on reassigning a foreign key. Whatever gave me that impression before, had to be a error elsewhere.

So it’s looking like my best fit is to use EF and just handle those few odd scenarios differently than I am now to make sure I don’t save any unwanted changes.