model driven architecture

Aug 15, 2010 at 7:32 PM

 Hello nHydrate team and anyone else who can help.

I am more than happy to pay for a consultaion if it means I can resolve this issue.  I am in serious need of a professional opinion on a model design problem that I find myself in.  Is there any way that the code below can be modified to encorporate all the tables in my current system, and future systems, without repeating the code?  For example, are there interfaces in the nHydrate model that can replace 'CustomersCollection' and 'Customers' in the code below, enabling all tables to pass through here via two intefaces.  Maybe I need implemnt new interfaces?

I am currently looking at class factories but think I am gloing down the wrong path.  Any help on this matter from the nHydrate team or any reader of this post, would be massively appreciated.  Also, if you wish not to answer, then I would really appreciate a point in the right direction as I have hit a brick wall mentaly with this one.

Thankyou for your time,

Robin.

                // get the record being edited from the database.
                int primaryKey = (int)keys[0];
                var databaseRecord = CustomersCollection.SelectUsingPK(primaryKey).First();


                // loop through the field constants and update the database record.
                foreach (Customers.FieldNameConstants field in Enum.GetValues(typeof(Customers.FieldNameConstants)))
                {
                    if (!DataMethods.ThisIsASystemField(field.ToString()) && field.ToString() != Customers.FieldNameConstants.Customerid.ToString())
                    {
                        if (objectsThatHaveBeenEdited.ContainsKey(field.ToString()))
                        {
                            databaseRecord.SetValue(field, formRecord.GetValue(field));
                        }
                    }
                }


                bool success = false;
                if (!databaseRecord.IsValid())
                {
                    ruleViolations.Clear();
                    foreach (IRuleViolation i in databaseRecord.GetRuleViolations())
                    {
                        ruleViolations.Add(i.Message);
                    }
                    success = false;
                }
                else
                {
                    databaseRecord.Persist();
                    success = true;
                }
                return success;

Coordinator
Aug 17, 2010 at 3:32 AM

I think you are looking for something like this. Please let me know if this suits you. In this example the "Test" method has your objects from your form. Since I did not have the full code I assumed these were the types. In each form you will need one line of code to define the primary key, objects edited, and rule violations. The "Process" method is generic and will work for any collection type you send in. This code will not compile with the version of nHydrate you have since we had to make significant modifications to make the collections more generic. This code does compile on the version I am using. If this looks good to you, we can proceed from there.

 

public void Test()
{
List<string> ruleViolations = new List<string>();
Dictionary<stringIPersistableBusinessObject> objectsThatHaveBeenEdited = null;

Process(new AncestorPrimaryKey(1), 
objectsThatHaveBeenEdited, 
ruleViolations);
}

public bool Process(IPrimaryKey pk, 
Dictionary<stringIPersistableBusinessObject> objectsThatHaveBeenEdited, 
List<string> ruleViolations)
{
SubDomain subdomain = new SubDomain();
IPersistableBusinessObject databaseRecord = subdomain.SelectUsingPK(pk) as IPersistableBusinessObject;

FieldNameConstantsAttribute attr = ReflectionHelper.GetAttributes(typeof(FieldNameConstantsAttribute), databaseRecord).First() as FieldNameConstantsAttribute;

// loop through the field constants and update the database record.
foreach (System.Enum field in Enum.GetValues(attr.TargetType))
{
System.Type enumType = databaseRecord.GetFieldNameConstants();
Enum pkEnum = (Enum)Enum.GetValues(enumType).GetValue(0);
if (!DataMethods.ThisIsASystemField(field) && field.ToString() != pkEnum.ToString())
{
if (objectsThatHaveBeenEdited.ContainsKey(field.ToString()))
{
var formRecord = objectsThatHaveBeenEdited[field.ToString()];
databaseRecord.SetValue(field, formRecord.GetValue(field));
}
}
}

bool success = false;
if (!databaseRecord.IsValid())
{
ruleViolations.Clear();
foreach (IRuleViolation i in databaseRecord.GetRuleViolations())
{
ruleViolations.Add(i.Message);
}
success = false;
}
else
{
databaseRecord.Persist();
success = true;
}
return success;

}

 

Aug 17, 2010 at 12:32 PM

Thankyou, I never expected such a response as this.  Yes, I think you are nearly there.  Forgive me if I am being premature with these points.

1.  IPersistableBusinessObject databaseRecord = subdomain.SelectUsingPK(pk) as IPersistableBusinessObject;

     Would this line of code would need to know what collection to apply itself against.  Maybe pass in a type when making the call ?

2.  You can remove objectsThatHaveBeenEdited from your thought preocess.  IPersistableBusinessObject _formRecord (declared in the aspx.cs) gets passed in, it is a blank record from the collection that gets populated with current onscreen activity and is what formRecord is what you assumed objectsThatHaveBeenEdited was.  I hope that made sence.

Does the code look good to me?  Marilyn Monroe dosen't look this good.  I can honestly say, I have never been happier to read through a section of code.  I am in baited breath to see how you continue with this.

I don't want to sound like a bore, but I have to thank you for you efforts, and thank you for helping me.  I will be making a donation in this regard (well, what little I can afford).  By the way can you make a donation without paypal ?

Thanks,

Robin

Aug 19, 2010 at 1:05 PM
Edited Aug 19, 2010 at 4:41 PM

Hi,

Did you make any progress  ? I can see from your activity that you have implemeted a few things.

Thanks for your time,

Rob

Coordinator
Aug 25, 2010 at 2:04 AM

Please download the latest version (173). You should be able to perform this action now with the enhanced base classes and interfaces. If you are still missing functionality please let me know.

Aug 25, 2010 at 11:45 AM

A genuine heart felt thankyou.  I shall try the new functionality today and let you know how it goes.  Thanks for your time, Rob.

Aug 26, 2010 at 12:50 AM
Edited Aug 26, 2010 at 2:49 PM

Your modifactions work perfectly, Thankyou.

I have a few questions :

1. I am currently implementing an interface ICanBeDeleted onto each business object.  Do you have any plans to implement an override or interface of this type onto the IPersistableBusinessObject in a similar vein to IValidation?

2. In your implementation of SelectUsingPK on the SubDoain class, the method signature has a return type of IBusinessObject yet you are returning business objects of different types.  What is the mechanism that allows for this ? I can then go and read up on it.

3. On testing I found that Enum pkEnum = (Enum)Enum.GetValues(enumType).GetValue(0); returns the first field alphabetically and not the primary key.  To get around this, I am currently pulling the primary key string on the form and passing it it to make a comparison.  Is this a bug or just example code ? I am happy either way ...

Thanks for your time,

Rob

Coordinator
Dec 3, 2010 at 1:03 AM

1. Why do you need ICanBeDeleted? If you want to know what is an immutable table, you can look for the interface on a BusinessObject named "ImmutableObject".

2. There are multiple business objects that can be returned from the subdomain so it returned the interface IBusinessObject. You must cast the object to the proper one. If you need a strongly typed BO then use the strongly-typed business object collection. The SelectUsingPK is typed for the actual business object on its collection type.

3. If you cast 0 as a field enum it will just return the first field. These are generated alphabetically so you are correct. If you need the enum of the primary key please search this type by attribute. There is a PrimaryKey attribute on te PK fields for this enum in the next version. Look at the generated code and you will see the attribute on this enum value. Use version 4.0.0.182.

If you are unfamiliar with Attributes you may need to lookup how to access these properties. It is not the most straight forward way to get data because it is reflection but this does provide a very robust way to describe data.

Dec 22, 2010 at 11:06 PM
Edited Dec 22, 2010 at 11:17 PM

Thanks for your help it is very much appreciated.