Someone want to make some money? I need CSLA help bad

Someone want to make some money? I need CSLA help bad

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


ataylorm posted on Wednesday, December 26, 2007

Good Evening,

Anyone feel like making a little extra dough?  I am faced with an object model that doesn't fit CSLA, no time, no resources, and no past experinenc with CSLA.  If you have some time tonight and could help me out with a seriously messy class I would be greatful.  It's about 1400 lines of code.

Basically here is the problem...

I have a user...  User works GREAT, but user has several subsets of data like UserAccount, UserProfile, UserDemographics, etc.  These are all currently subclasses so like User.UserAccount, User.UserProfile, etc.  Each contains different user data from different tables.

Where I seem to be stuck is getting CSLA to understand that UserAccount is a sub-set of User and it needs to be based on the userid and validate it's own properies and such.

UserAccount, UserProfile, and UserDemographics should not load any data until they are specifically initialized.

If I can send you a zip and you can help me out, I would GREATLY appreciate it and can paypal you some funds ASAP (or rentacoder them if you prefer).

Thanks,

Andrew

ataylorm replied on Wednesday, December 26, 2007

It might actually be better for me to just have someone start this sucker from scratch because I imagine it will take more time to sort through all my code than it will to just frame it out from scratch.  So let me lay out what we have, and that way maybe someone can shoot me over a price and a time frame (hopefully tonight).

Tables:

User
   - UserGUID (Read Only)
   - UserName
   - Password
   - FirstName
   - LastName
   - EmailAddress
   - isActive (Read Only)


UserAccount
   - UserGUID
   - PhoneNumber
   - MobileNumber


UserAddresses
   - UserGUID
   - Address1
   - Address2
   - City
   - State
   - ZipCode
   - Country


UserProfile
UserDemographics
UserPreferences
UserPaymentMethods

Basically the way the boss wants this, is that User is the main record, and each of the subsets of data isn't loaded until/if the user accesses a function that needs that data.  (Planning for millions of users)

So the way it's envisioned is that I will load a user, then if I need a useraccount or userprofile I will instantiate that data off the User object I have already created.

User tmpUser = User.GetUserByUserName("afksldfjlsa");

UserAccount tmpAccount = User.UserAccount;

Now it's entirely possible to save a User record with no Account, Profile, etc.  However you can only save UserAccount if you have a valid User created.

To through in another twist, Addresses are a collection in UserAccount, so it would be like:

string strAddress1 = tmpUser.UserAccount.Addresses[0].Address1;

Which I of course need to be able to add to and remove from.

I won't even worry about the other sub-classes because they can all be based off the same framework.

 

Look forward to finding someone that can help me figure out this tangled mess.

Thanks,

Andrew

Marjon1 replied on Wednesday, December 26, 2007

Andrew,

I'm happy to investigate this further with you, please see the email that I sent.

Regards,

John

Brent Dunham replied on Thursday, December 27, 2007

Take a look at the classes below:

public class User

{

private Guid _Id;

public Guid Id

{

get { return _Id; }

}

private UserDemographics _Demographics;

public UserDemographics Demographics

{

get

{

if (_Demographics == null)

{

_Demographics = UserDemographics.GetUserDemographics(_Id);

}

return _Demographics;

}

}

private UserAccount _Account;

public UserAccount Account

{

get

{

if (_Account == null)

{

_Account = UserAccount.GetUserAccount(_Id);

}

return _Account;

}

}

private UserAddressList _Addresses;

public UserAddressList Addresses

{

get

{

if (_Addresses == null)

{

_Addresses = UserAddressList.GetUserAddressList(_Id);

}

return _Addresses;

}

}

public static User GetByUserName(string userName)

{

throw new NotImplementedException();

}

}

public class UserDemographics

{

internal static UserDemographics GetUserDemographics(Guid guid)

{

throw new NotImplementedException();

}

}

public class UserAccount

{

internal static UserAccount GetUserAccount(Guid guid)

{

throw new NotImplementedException();

}

}

public class UserAddress

{

internal static UserAddress GetUserAddress(SafeDataReader reader)

{

throw new NotImplementedException();

}

public static UserAddress NewUserAddress()

{

throw new NotImplementedException();

}

}

public class UserAddressList

{

internal static UserAddressList GetUserAddressList(Guid guid)

{

// Here you would (if using CSLA) call dataportal_fetch.

// Inside dataportal_fetch (or here if not using CSLA)

// Do something like this:

using (SqlConnection cn = new SqlConnection())

{

cn.Open();

using (SqlCommand cmd = cn.CreateCommand())

{

cmd.CommandText = ""; // fecth all addresses for the user

using(SafeDataReader reader = new SafeDataReader(cmd.ExecuteReader()))

{

this.Add(UserAddress.GetUserAddress(reader));

}

}

}

throw new NotImplementedException();

}

}

 

Formatting didn't copy well but...

First thing to note is I don't see a reason for sub-classes. Just because a User contains a UserDemographics object doesn't infer sub-classing.

What I'm trying to demonstrate with the property being exposed for User.DemoGraphics is that the property is not loaded until accessed. This is often refered to as deferred loading or lazy loading. This enables a lighter-weight object initially, but allows retrieval in a intuitive way. Notice the factory method for UserDemographics is internal to not confuse users of the OM. The UserAddressList is a collection of UserAddress instances. It is also lazy loaded. What I'm trying to demostrate here is that the UserAddressList actually does the data access and passes a reader to the UserAddress factory method. I also exposed a public factory method for UserAddress called NewUserAddress. This would pass a new UserAddress back that is mark New (.IsNew = true) that can be added to the UserAddressList class. I did not address anything related to CSLA other than the SafeDataReader. If you do not have experience with CSLA, then that's likely to be a slightly different topic.

You would likely need to implement the following:

Normal fields / Properties

IsDirty / IsValid / IsNew / IsChild

DataPortal_Fetch / DataPortal_Insert / DataPortal_Update (data access)

There are quite a few other thing depending on how complete / rich you would like the objects.

As a note on the Save:

If the Controller calls User.Save, you might want to check if each of the child objects in the User object have been instanciated before calling IsDirty / IsValid etc. What I've done in the past is something like this:

public bool IsDirty

{

get

{

return base.IsDirty || (_Demographics==null ? false : _Demographics.IsDirty) || ...

}

}

Hope that helps,

Brent

 

Copyright (c) Marimer LLC