I have a colleague who has come up with a way of 'genericizing' information from a database so that all his web application's drop-down lists can share the same object in his MVC.NET C# code and Views, which can contain different data depending on what tables it is being used against.
We work for a government agency, and we have facilities divided up into areas called "Regions", which contain further subdivided areas called VISNs, which each contain "Sites" or "Facilities". My colleague has developed a very complex security scheme whereby people can be granted access to data based on their permission level which can be assigned by Region, VISN, Site, or any mixture of the three. It's a nice scheme and very clever. However, he has stored procedures that return lists of Regions, VISNs, and Sites based on a person's User Id, and he is returning "generic" values like TextFieldID
, TextField
, and TextParentID
. My first problem with this, is that looking at this data coming out of the database, I would not know what the data is. I feel that fields coming from a query or stored procedure should be descriptive of the data they are delivering. What does everyone else think? The deeper issue for me however is that he is taking some of the data, concatenating it in his stored procedure like this
SELECT DISTINCT
t.VisnID,
NULL,
t.StationID,
'V' + CAST(t.VisnID as varchar) + ': ' + t.Station3N + ': ' + t.StationName,
t.Inactive
FROM Stations t
and sending it back in a "TextField" property, instead of sending back the discrete data separately (Station3N
, StationName
) and concatenating it in the View, which would allow for different concatenation depending on what device what accessing the application (perhaps mobile and desktop). His justification is that he can send all his various drop down data and capture them all, regardless of content, in the same C# object named "LookupValue."
public partial class LookupValue : IEquatable<LookupValue>
{
public LookupValue(string textFieldId, string textField, bool inactive)
{
TextFieldID = textFieldId;
TextField = textField;
Inactive = inactive;
}
public LookupValue(string textParentId, string textFieldId, string textField, bool inactive)
{
TextParentID = textParentId;
TextFieldID = textFieldId;
TextField = textField;
Inactive = inactive;
}
public LookupValue(string textParentId, string textSelfParentId, string textFieldId, string textField, bool inactive)
{
TextParentID = textParentId;
TextSelfParentID = textSelfParentId;
TextFieldID = textFieldId;
TextField = textField;
Inactive = inactive;
}
/// <summary>
/// Returns a custom string identifier if the Inactive property is true.
/// </summary>
public string GetInactiveString()
{
string value = "";
if (Inactive)
{
value = "[I]";
}
return value;
}
/// <summary>
/// Returns a custom text label that concatenates the TextField property with the custom string identifier of the Inactive property.
/// </summary>
public string GetDisplayNameWithInactiveString
{
get { return TextField + " " + GetInactiveString(); }
}
public bool Equals(LookupValue other)
{
//Check whether the compared object is null.
if (Object.ReferenceEquals(other, null)) return false;
//Check whether the compared object references the same data.
if (Object.ReferenceEquals(this, other)) return true;
//Check whether the products' properties are equal.
return TextFieldID.Equals(other.TextFieldID) && TextField.Equals(other.TextField);
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public override int GetHashCode()
{
//Get hash code for the TextFieldID field if it is not null.
int hashTextFieldId = TextFieldID == null ? 0 : TextFieldID.GetHashCode();
//Get hash code for the Code field.
int hashTextField = TextField.GetHashCode();
//Calculate the hash code for the product.
return hashTextFieldId ^ hashTextField;
}
}
He believes the re-usability of this object is worth the violation of Separation of Concerns and possible future difficulties in handling more than one display variation for a drop-down. I should point out that this object is contained in his Data project namespace (our projects are separated into Data, Web, Services, etc.) instead of the Web project namespace and he also returns this object to the Web layer via his Repository queries which call the stored procedures that I described earlier, which is gross violation of Separation of Concerns in my opinion.
I am just looking for some confirmation from other programmers that this is in fact a bad practice, and also looking for ideas I can present him on better ways to do what he is attempting. I have my own ideas, but again I'm just looking for other's ideas so I have more options to present to him.
--Edit -- I forgot to mention that we are using Entity Framework as an ORM, and his Repository classes in his DAL are dumping the data from the stored procs into this LookupValue object.