A very annoying issue in BusinessListBase

A very annoying issue in BusinessListBase

Old forum URL: forums.lhotka.net/forums/t/5218.aspx


Cuong posted on Friday, August 08, 2008

I am developing a small software of school management. In each new school-year the user must do some changes to transfer data from old school-year. Eg, pupils in class 1A will become in class 2A, pupils in class 1B will become in class 2B ... (the number 1, 2 means grade numbers).

For more clearly, I propose here a simple scenario. My db has a table named TBL_Class that has only 1 field [ClassName] (this field is also marked as PrimaryKey). This table has records like bellow:

TBL_Class (ClassName)
-----------------------------
1A
1B
2A
2B
3A
3B
-----------------------------

As normally, I will create 2 classes in BusinessLogic layer:

[Serializable]
puplic class Class : BusinessBase<Class>
{
    ...
    public string ClassName { ... }
    ...
}

[Serializable]
puplic class ClassList : BusinessBaseList<ClassList, Class>
{
    ...
}

In each new school-year, the user will make changes on ClassList like bellow:

ClassList list = ClassList.GetClassList();

// Delete class of the last grade (3A, 3B)
list.RemoveAt(5);
list.RemoveAt(4);

// Changes 2B->3B, 2A->3A, 1B -> 2B, 1A -> 2A
list[3].ClassName = "3B";
list[2].ClassName = "3A";
list[1].ClassName = "2B";
list[0].ClassName = "2A";

// Add 2 new classes 1A, 2A
Class item;
item = list.AddNew()
item.ClassName = "1A";
item = list.AddNew()
item.ClassName = "1B";

// Error will occur when Save
list.Save();
----------------- End ----------------

You see that all changes user has done with ClassList are totally correct but user cannot Save the list to db. An error always occurs.

If you read the code of BusinessBaseList.Save method you will see the list Saves dirty items from begin to end of list. In my scenario:
1. ClassList Delete 2 item "3B", "3A". That's OK, no error. Now the table TBL_Class has 4 records ("1A", "1B", "2A", "2B")
2. ClassList Saves dirty items. Firstly, ClassList saves the first item "2A" in to the first record. Unfortunately, the TBL_Class already contains "2A" in the third record. So the error occurs.

Until now, I cannot find any good solution to resolve this issues. I hope to receives suguestions to resolve this headadche problem.

Thank you very much.

rsbaker0 replied on Saturday, August 09, 2008

This problem really isn't specific to BusinessListBase (BLB). If you had been using another interface that saved the changes as you went, you would have gotten errors as you went along.

Anytime you are reusing primary keys like this there is the potential for problems for which the solution can be non-trivial.

One possibility (haven't looked at the CSLA code) would be for you to override the Save() code and save the items in an order that the database would allow, but this would require you to analyze the changes and save the non-conflicting ones first.

I still think there is the potential for problems you can't solve this way, though.

Say you only have 2 items in your list, 1A and 2A.

The user wants to swap these. This cannot be done in one step like you are proposing without an intermediate rename of one of the classes to some other value that the user didn't even directly specify.

(That being said, maybe you could craft a soluton that renames ALL the items in the list to some temporary value say you put -T at the end, and then renames them again to the desired user values)

 

Cuong replied on Saturday, August 09, 2008

This problem really isn't specific to BusinessListBase (BLB). If you had been using another interface that saved the changes as you went, you would have gotten errors as you went along.

I am 100% sure there is not any error in code of Class and ClassList.

Anytime you are reusing primary keys like this there is the potential for problems for which the solution can be non-trivial.

For a simplified scenario, so I propose the TBL_Class have only filed ClassName. The same error also occurs if I add ClassId filed and mark it as PrimaryKey.  Of course in this case the ClassName has UniqueKey.

One possibility (haven't looked at the CSLA code) would be for you to override the Save() code and save the items in an order that the database would allow, but this would require you to analyze the changes and save the non-conflicting ones first.

The snippet code above only mimics a case that user usually does to transfer data from old school-year to new school-year. But user can do many other ways.

I still think there is the potential for problems you can't solve this way, though.Say you only have 2 items in your list, 1A and 2A.

Of course, no error occurs if there are 2 items in ClassList. Maybe my English is too bad so you did not understand exactly this issue.



rsbaker0 replied on Sunday, August 10, 2008

I based my reply on this specific reference to the error in your first post:

Cuong:

2. ClassList Saves dirty items. Firstly, ClassList saves the first item "2A" in to the first record. Unfortunately, the TBL_Class already contains "2A" in the third record. So the error occurs.

So, you are trying to save multiple primary key changes at the same time. If a record with a primary particular key value already exists in the database, it can't be saved.

So, your other 2A record has to be renamed "out of the way" before the first one can be saved. The user changed it's name, so if it has been saved first, it might have worked, but my last comment was that you can contrive a case when the user is manually changing keys like this that can't be solved without programmatically doing a temporary rename of the values to avoid a key conflict.

 

rsbaker0 replied on Monday, August 11, 2008

From your first post:

My db has a table named TBL_Class that has only 1 field [ClassName] (this field is also marked as PrimaryKey).

So, I assume you are getting a primary key violation (for reasons I discussed earlier).

One approach you might consider this that would avoid the problem is having an explicit "Promote" function to promote a class from one grade to the next. This function could delete the existing class (e.g. if it's the last grade and isn't needed any more) first, and then apply the class name change to the class that is moving up.

DancesWithBamboo replied on Monday, August 11, 2008

This looks much more like a database design issue than a CSLA one.  You are using a natural key (ClassName) when you need a surrogate key.  Since the data that you are using as a primary key is variable (changes each year), you end up with changing keys.  This rarely works. is almost always a sign that something is wrong, and as you have found, non-trival to implement.

I would suggest that you create a "real" primary key column (like ClassId) for each class of pupils (int or guid) to your Class table.   Make your classnames value (1A, 1B) a foreign key to a "ClassNames" table.  Then you will be able to just update the ClassName pointer when you roll-over the year.

I would also think you would want YearFrom and YearTo fields on your Class table and then do new inserts when you roll over the year.  Otherwise you are overwriting last year's data with no historical record?   Actually if you added these to your ClassName key you would end up with a compsite key (classname, yearto, yearfrom) that would allow you to roll forward the year by doing an insert without the need for the serrogate key.

Of course one nice thing about using the ClassId key would be that other tables such as Pupil could reference the Class table by a single key; thus simplifying the joins.

Cheers.

phucphlq replied on Sunday, August 10, 2008

You should give here errors for more detail. I think you use incorrect template?

Which template do you use for Class? ClassList? Lookup in Template folder

 

 

 

 

 

 

 

 

 

 

Are you from Vietnam? Contact me at yahoo chat: nhat_nam_2008

 


From: Cuong [mailto:cslanet@lhotka.net]
Sent: Saturday, August 09, 2008 08:37
To: phucphlq@softech.vn
Subject: [CSLA .NET] A very annoying issue in BusinessListBase

 

I am developing a small software of school management. In each new school-year the user must do some changes to transfer data from old school-year. Eg, pupils in class 1A will become in class 2A, pupils in class 1B will become in class 2B ... (the number 1, 2 means grade numbers).

For more clearly, I propose here a simple scenario. My db has a table named TBL_Class that has only 1 field [ClassName] (this field is also marked as PrimaryKey). This table has records like bellow:

TBL_Class (ClassName)
-----------------------------
1A
1B
2A
2B
3A
3B
-----------------------------

As normally, I will create 2 class in BusinessLogic layer:

[Serializable]
puplic class Class : BusinessBase<Class>
{
    ...
    public string ClassName { ... }
    ...
}

[Serializable]
puplic class ClassList : BusinessBaseList<ClassList, Class>
{
    ...
}

In each new school-year, the user will make chages on ClassList like bellow:

ClassList list = ClassList.GetClassList();

// Delete class of the last grade (3A, 3B)
list.RemoveAt(6);
list.RemoveAt(5);

// Changes 2B->3B, 2A->3A, 1B -> 2B, 1A -> 2A
list[4].ClassName = "3B";
list[3].ClassName = "3A";
list[2].ClassName = "2B";
list[1].ClassName = "2A";

// Add 2 new classes 1A, 2A
Class item;
item = list.AddNew()
item.ClassName = "1A";
item = list.AddNew()
item.ClassName = "1B";

// Error will occurs when Save
list.Save();
----------------- End ----------------

You will see that all changes user has done with ClassList are totally correct but user cannot Save the list to db. An error always occurs.

If you read the code of BusinessBaseList.Save method you will see the list Saves dirty-items from begin to end of list. In my scenario:
1. ClassList Delete 2 item 3B", "3A". That' OK, no error. Now the table TBL_Class has 4 records ("1A", "1B", "2A", "2B")
2. ClassList Saves dirty items. Firstly, ClassList saves the item "2A" in to the first record. Unfortunately, the TBL_Class already contains "2A" in the third record. So the error occurs.

Until now, I cannot find any good solution to resolve this issues. I hope to receives suguestions to resolve this headadche proble.

Thank you very much.



Cuong replied on Monday, August 11, 2008

Yes, I am from VN (Vinh, Nghe An).

I already described the reason why the error occurs in post #1. And I am 100% sure there is not any error in code of Class, ClassList.

Copyright (c) Marimer LLC