I have a SalesmanRepository that simply lists all the salesmen from my database.
I want to display the result in a grid (imagine a Web interface), so the user can display or hide any field, sort a column and use paging.
Let's assume I have a very large set, so the sorting and paging must be server-side.
My question is, how can I stay loosely-coupled in my architecture?
I don't want my database column's name to the binded to the UI's columns. I want to have the flexibility to change for a new type of database later.
How should I handle paging? By adding parameters such as page and numberOfItemsPerPage directly to the repository's method for example?
How should I approach sorting as well? I don't want either to bind the database column's name to the sorting parameter, as in I could have a new type of database and I would break all my software.
Basically, how can I approach these concept and stay loosely coupled? Ideally, I would like a language-agnostic approach, but I'm using C# if there is a better language-specific answer.
EDIT : My question can be more precise as is: how can I tell my repository to sort by a field, without mentioning the name of the field directly?
EDIT 2: I want to tell my repository to sort by a field, but I don't want to be binded to the implementation since the interface of my Repository is in my business logic layer (or domain layer).
Let's assume I have a MySQL database (hence a SalesmanMySQLRepository) with a table named Salesman that includes a column Name.
Let's say now that I also have a SQL Server database (with a SalesmanSQLRepository) with a table named Salesman that includes the same column Name, but here I would name it instead BobbyName because my team decided to have some sort of prefix at columns for whatever reason. It is detail-specific and has nothing to do with business logic.
How is my SalesmanRepository should look like? I don't want to send a string directly as in each implementation is completely different. I guess there would be a method like PagedResult<Salesman> List(SortingParameter field), but how should I handle this parameter?
I did it once. I resolved this issue by creating a object like:
public class ClientPage
{
private int PageIndex;
private int PageLengh;
private List<Client> Clients;
private int ClientsCount;
}
So I could manage pages instead of clients list.
Hope this helps you somehow.
it seems that you don't want paging and sorting on both client and database, so, i think the only place you can do paging and sorting is in memory, so you can code a shared method like
public static IEnumerable<T> SortingAndPaging<T>(IEnumerable<T> entities, int pageSize, int pageNum, string sortField, string order)
{
//your sorting and paging logic goes here, maybe Linq is helpful here
}
by this, we can achieve Database agnostic
I would solve by sending the text in the column header to the back end as what I want to sort by and then use reflection to find that property name in the object. You'll need to make sure the display name in the column is convertible to the field name by algorithm or by lookup. The code below is pseudo-ish, but the method is solid.
Front End:
<th class="sortable">Last Name</th> ...
$('.sortable').onClick(function(event){
//send request to backend with text of header as sortBy
...
});
Back End:
List<Person> GetPeople ( string sortBy )
{
//Person has property lastName
var propery = Person.GetField(SortByStringToPropertyName(sortBy));
List<Person> people = db.Persons.OrderBy(property).ToList();
return people;
}
Related
I am writing a program where data is being displayed using a DataGridView and I was hoping there was a way to access the visible property of the columns without specifying the index location, or Column Name string value.
public class test {
public static string value1 { get; set; }
public static string value2 { get; set; }
}
I am using the LINQ to SQL datacontext to query information to be displayed into my DataGridView.
As it currently is, I can only seem to find a way to change the Columns visible property as so (assuming DataGridView is instantiated as dgvDATA)
dgvDATA.columns["value1"].visible = false;
Is there any way to do something similar to the following? I assume if there is it would be through databindings, but I tried that and couldn't figure it out.
dgvDATA.column.value1.visible = false;
I found this article stating that the DataGridView does not have this kind of ability built in but there was a workaround where you could add a database field representing if you want it visible or not.
HOWEVER the article was written in 2011 so I find it hard to believe that something like this was never implemented.
https://dotnetbuildingblocks.wordpress.com/2011/07/30/binding-datagrid-column-visibility-to-a-datacontext/
Please let me know if this is possible! Thank you
DataGridView doesn't support what you are asking for.
Anyway, if your only goal is to avoid using hardcoded field names, then using nameof() makes sense.
In your case it will be
dgvDATA.Columns[nameof(test.value1)].Visible = false;
That way you will have no issues refactoring your code later.
Apparently you want some kind of special DataGridViewColumn, where columns can be identified using some identification that is not available in a standard DataGridViewcolumn. For example you want to identify them by the PropertyInfo of the property that is shown in the column, or maybe the database column name of the database column whose values you show in this column.
In object oriented programming, if you want to create a special kind of DataGridViewColumn you should write a derived class:
class MySpecialDataGridViewColumn : DataGridViewColumn
{
public string DatabaseColumnName {get; set;}
}
Normally this would be enough: as long as you make sure that you only add MySpecialDataGridViewColumn objects to your DataGridView. When you fetch a column, typecast it to MySpecialDataGridViewColumn.
var theColumnThatDisplaysFirstName = myDataGridView.Columns // get all columns
.Cast<MySpecidalDataGridViewColumn>() // cast to your type
.Where(column => column.DatabaseCollumnName == "FirstName")
.SingleOrDefault(); // keep the ones with "FirstName"
Be aware that others will still be able to Add other kind of columns to your DataGridView. If you are afraid of this, make sure that you keep your members private and add functionality to Add / Fetch / Remove MySpecialDataGridViewColumns.
If your DataGridView is to be used by many, consider creating a UserControl that contains a private DataGridView, with functionalities to Add / Retrieve / Remove MySpecialDataGridViewColumn objects to the user control. This way others can't misuse your `DataGridView by adding other types of columns
Of course, if you want to allow others to add their own kind of Columns, you could always use OfType<MySpecialDataGridViewColumn> instead of a Cast. This way you ignore the other type of added columns, of which you are certain that they don't display your database columns
I am tacking a large refactor of a project, and I had asked this question to confirm/understand the direction I should go in and I think I got the answer that I wanted, which is not to throw away years worth of code. So, now begins the challenge of refactoring the code. I've been reading Martine Fowler and Martin Feathers' books, and they have a lot of insight, but I am looking for advice on the ultimate goal of where I want the application to be.
So to reiterate the application a little bit, its a dynamic forms system, with lots of validation logic and data logic between the fields. The main record that gets inserted is the set of form fields that is on the page. Another part of it is 'Actions' that you can do for a person. These 'Actions' can differ client by client, and there are hundreds of 'Actions'. There is also talk that we can somehow make an engine that can eventually take on other similar areas, where a 'person' can be something else (such as student, or employee). So I want to build something very de-coupled. We have one codebase, but different DBs for different clients. The set of form fields on the page are dynamic, but the DB is not - it is translated into the specific DB table via stored procs. So, the generic set of fields are sent to the stored proc and the stored proc then decides what to do with the fields (figure out which table it needs to go to). These tables in fact are pretty static, meaning that they are not really dynamic, and there is a certain structure to it.
What I'm struggling specifically is how to setup a good way to do the dynamic form control page. It seems majority of the logic will be in code on the UI/aspx.cs page, because its loading controls onto the webpage. Is there some way I can do this, so it is done in a streamlined fashion, so the aspx.cs page isn't 5000 lines long? I have a 'FORM' object, and one of the properties is its' 'FIELDS'. So this object is loaded up in the business layer and the Data layer, but now on the fron end, it has to loop through the FIELDS and output the controls onto the page. Also, someway to be able to control the placement would be useful, too - not sure how do get that into this model....
Also, from another point of view - how can I 'really' get this into an object-oriented-structure? Because technically, they can create forms of anything. And those form fields can represent any object. So, for example, today they can create a set of form fields, that represent a 'person' - tomorrow they can create a set of form fields that represent a 'furniture'. How can I possibly translate this to to a person or a furniture object (or should I even be trying to?). And I don't really have controls over the form fields, because they can create whatever....
Any thought process would be really helpful - thanks!
How can I possibly translate this to to a person or a furniture object
(or should I even be trying to?)
If I understand you correctly, you probably shouldn't try to convert these fields to specific objects since the nature of your application is so dynamic. If the stored procedures are capable of figuring out which combination of fields belongs to which tables, then great.
If you can change the DB schema, I would suggest coming up with something much more dynamic. Rather than have a single table for each type of dynamic object, I would create the following schema:
Object {
ID
Name
... (clientID, etc.) ...
}
Property {
ID
ObjectID
Name
DBType (int, string, object-id, etc.)
FormType ( textbox, checkbox, etc.)
[FormValidationRegex] <== optional, could be used by field controls
Value
}
If you can't change the database schema, you can still apply the following to the old system using the stored procedures and fixed tables:
Then when you read in a specific object from the database, you can loop through each of the properties and get the form type and simple add the appropriate generic form type to the page:
foreach(Property p in Object.Properties)
{
switch(p.FormType)
{
case FormType.CheckBox:
PageForm.AddField(new CheckboxFormField(p.Name, p.Value));
break;
case FormType.Email:
PageForm.AddField(new EmailFormField(p.Name, p.Value));
break;
case FormType.etc:
...
break;
}
}
Of course, I threw in a PageForm object, as well as CheckboxFormField and EmailFormField objects. The PageForm object could simply be a placeholder, and the CheckboxFormField and EmailFormField could be UserControls or ServerControls.
I would not recommend trying to control placement. Just list off each field one by one vertically. This is becoming more and more popular anyway, even with static forms who's layout can be controlled completely. Most signup forms, for example, follow this convention.
I hope that helps. If I understood your question wrong, or if you'd like further explanations, let me know.
Not sure I understand the question. But there's two toolboxes suitable for writing generic code. It's generics, and it's reflection - typically in combination.
I don't think I really understand what you're trying to do, but a method using relfection to identify all the properties of an object might look like this:
using System.Reflection;
(...)
public void VisitProperties(object subject)
{
Type subjectType = subject.GetType();
foreach (PropertyInfo info in subjectType.GetProperties()
{
object value = info.GetValue(subject, null);
Console.WriteLine("The name of the property is " + info.Name);
Console.WriteLine("The value is " + value.ToString());
}
}
You can also check out an entry on my blog where I discuss using attributes on objects in conjunction with reflection. It's actually discussing how this can be utilized to write generic UI. Not exactly what you want, but at least the same principles could be used.
http://codepatrol.wordpress.com/2011/08/19/129/
This means that you could create your own custom attributes, or use those that already exists within the .NET framework already, to describe your types. Attributes to specify rules for validation, field label, even field placement could be used.
public class Person
{
[FieldLabel("First name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(1)]
[FormRow(1)]
public string FirstName{get;set;}
[FieldLabel("Last name")]
[ValidationRules(Rules.NotEmpty | Rules.OnlyCharacters)]
[FormColumn(2)]
[FormRow(1)]
public string LastName{get;set;}
}
Then you'd use the method described in my blog to identify these attributes and take the apropriate action - e.g. placing them in the proper row, giving the correct label, and so forth. I won't propose how to solve these things, but at least reflection is a great and simple tool to get descriptive information about an unknown type.
I found xml invaluable for this same situation. You can build an object graph in your code to represent the form easily enough. This object graph can again be loaded/saved from a db easily.
You can turn your object graph into xml & use xslt to generate the html for display. You now also have the benefit of customising this transform for differnetn clients/versions/etc. I also store the xml in the database for performance & to give me a publish function.
You need some specific code to deal with the incoming data, as you're going to be accessing the raw request post. You need to validate the incoming data against what you think you was shown. That stops people spoofing/meddling with your forms.
I hope that all makes sense.
Although the problem I'll be detailing in this question is quite specific, I guess it should help some other beginner programmers like me. I have this following situation: in the system I'm designing, the user has the option to set the values for his search in the database (instead of just routing the parameter of the controller action to the id of a object in the database, as I've done before), with the following fields:
Power Plant (Drop down list of all of the existing Power Plants)
Generating Units (List box with multiple selection that displays the generating units of the selected Power Plant)
Period (A drop down list with the available time spans, like "Last 7 days" and "Last Month")
Beginning and End Time (If instead of selecting a predefined time, the user wants to define the specific time span)
How can I put this elements on a page and search for the specified values in the database? I mean, how do I make this fields an object that I can send to the POST action, so it can compare to the database and get the values? What I've tried to do included create an editor template for this (but I couldn't understand what I was doing), and also I tried creating a controller to deal with this queries, so I could render just the query in the other pages (but I ended up with a page inside a page, in the best of "yo dawg I haerd u liek" style).
Can you guys give me some help, so I don't have to give up being a programmer and become a rapper?
It is a good example:
http://weblogs.asp.net/rajbk/archive/2010/05/08/asp-net-mvc-paging-sorting-filtering-using-the-mvccontrib-grid-and-pager.aspx
I think it is written in MVC 2, but can easily be converted to 3.
I don't quite understand from your question what entity you are filtering in your view, so i'll just call it "Entity".
in your controller you should have an entity repository (if you are unfamilier with the repository pattern you should look it up)
if you got that set up, filtering shouldn't be too difficult:
Create a view model class as followes:
public class EntityFilterViewModel()
{
string PowerPlanet {get;set;}
string GeneratingUnits {get;set;}
string Period{get;set;} // Simplification, you should use timespan or something.
DateTime BeginTime {get;set;}
DateTime EndTime {get;set;}
}
Next, Have a controller method like this:
public ActionResult Filter(EntityFilterViewModel model)
{
var result = from e in _entityRepository.Entites
where e.PowerPlanet.Equals(model.PowerPlanet) &&
e.GeneratingUnits.Equals(model.GeneratingUnits) &&
e.Periond.Equals(model.Period)
// other filters you would want...
return View("List", result); // use the overload which takes a view name and a viewmodel object
}
You should remember though to account for situations in which the user hasn't filled all the fields in the filtering form
I've created two classes in business layer.
the first one is called Users with id (int), pass (string) and privileges (Privilege) properties and the second one is called Privilege and has id (int) and privilegeName (string) properties.
I've a method that returns all the users, and I use a repeater (actually I bind it to a DataList to auto create the ItemTemplate for me and then use a repeater) and it works and displays all the properties well except for my List property. it generates instead something like this System.Collections.Generic.List`1[WebApplication2.Public.BLL.Users]
I want to display it in a friendly way like "User Privileges : Privi1, Privi2" but still I want to keep the layers of my application clean and structured, for example I won't store them in a database in the same table and just store them as a text and append it.
I hope to find a simple and good solution...Thanks in advance guys =)
PS : I don't want to display the object Privilege, I want to display privilege.privilegeName
When using repeaters, there are two approaches, one is the one suggested by Bugai13: to have a custom property that displays it. This is fine for certain types of nested data.
Your other option is to just have a repeater inside a repeater, and bind it appropriately (to what would be a list assigned to your main data object, depending on how you O/R Mapper works).
You can have the code for the custom display property not in the data model, but in your presentation layer somewhere (depending on your framework/design), so it's not a "bad" thing to do that. It's up to you, with whatever "feels" best.
Just create property at your Bussiness object, and bind it:
public string PrivilegiesString
{
get
{
var sb = new StringBuilder("User Privileges : ");
foreach(var item in privileges)
{
sb.AppendFormat("{0}, ",item.privilegeName);
}
return sb.ToString();
}
}
Suppose I have a table in my database that is made up of the following columns, 3 of which uniquely identify the row:
CREATE TABLE [dbo].[Lines]
(
[Attr1] [nvarchar](10) NOT NULL,
[Attr2] [nvarchar](10) NOT NULL,
[Attr3] [nvarchar](10) NOT NULL,
PRIMARY KEY (Attr1, Attr2, Attr3)
)
Now, I have an object in my application that represents one of those lines. It has three properties on it that correspond to the three Attr columns in the database.
public class Line
{
public Line(string attr1, string attr2, string attr3)
{
this.Attr1 = attr1;
this.Attr2 = attr2;
this.Attr3 = attr3;
}
public Attr1 {get; private set;}
public Attr2 {get; private set;}
public Attr3 {get; private set;}
}
There's a second object in the application that stores a collection of these line objects.
Here's the question: What is the most appropriate design when referencing an individual line in this collection (from a caller's perspective)? Should the caller be responsible for tracking the index of the line he's changing and then just use that index to modify a line directly in the collection? Or...should there be method(s) on the object that says something to the effect of:
public GetLine(string attr1, string attr2, string attr3)
{
// return the line from the collection
}
public UpdateLine(Line line)
{
// update the line in the collection
}
We're having a debate on our team, because some of us think that it makes more sense to reference a line using their internal index in the collection , and others think there's no reason to have to introduce another internal key when we can already uniquely identify a line based on the three attributes.
Thoughts?
Your object model should be designed so that it makes sense to an object consumer. It should not be tied to the data model to the greatest extent practical.
It sounds like it is more intuitive for the object consumer to think in terms of the three attributes. If there are no performance concerns that speak to the contrary, I would let the object consumer work with those attributes and not concern him with the internal workings of data storage (i.e. not require them to know or care about an internal index).
I think the base question you are encountering is how much control the user of your API should have over your data, and what exactly you expose. This varies wildly depending on what you want to do, and either can be appropriate.
The question is, who is responsible for the information you wish to update. From what you have posted, it appears that the Line object is responsible the information, and thus I would advocate a syntax such as Collection.GetLine(attr1, attr2, attr3).UpdateX(newX) and so forth.
However, it may be that the collection actually has a greater responsibility to that information, in which case Collection.UpdateX(line, newX) would make more sense (alternatively, replace the 'line' arg with 'attr1, attr2, attr2').
Thirdly, it is possible, though unlikely (and rarely the best design IMHO) that the API user is most responsible for the information, in which case an approach you mentioned where the user handles tracking Line indices and directly modifies information.
You do not want the calling object to "track the index of the line he's changing" - ever. This makes your design way too interdependent, pushes object-level implementation decisions off onto the users of the object, makes testing more difficult, and can result in difficult to diagnose bugs when you accidentally update one object (due to key duplications) when you meant to update another.
Go back to OO discipline: the Line object that you are returning from the GetLine method should be acting like a real, first class "thing."
The complication, of course, comes if you change one of the fields in the line object that is used as part of your index. If you change one of these fields, you won't be able to find the original in the database when you go to do your update. Well, that is what data hiding in objects is all about, no?
Here is my suggestion, have three untouchable fields in the object that correspond to its state in the database ("originalAttr1", "originalAttr2", "originalAttr3"). Also, have three properties ("attr1", "attr2", "attr3") that start out with the same values as the originals but that are Settable. Your Getters and Setters will work on the attr properties only. When you "Update" (or perform other actions that go back to the underlying source), use the originalAttrX values as your keys (along with uniqueness checks, etc.).
This might seem like a bit of work but it is nothing compared to the mess that you'll get into if you push all of these implementation decisions off on the consumer of the object! Then you'll have all of the various consumers trying to (redundantly) apply the correct logic in a consistent manner - along with many more paths to test.
One more thing: this kind of stuff is done all the time in data access libraries and so is a quite common coding pattern.
What is the most appropriate design
when referencing an individual line in
this collection (from a caller's
perspective)?
If the caller is 'thinking' in terms of the three attributes, I would consider adding an indexer to your collection class that's keyed on the three attributes, something like:
public Line this[string attr1, string attr2, string attr3] {
get {
// code to find the appropriate line...
}
}
Indexers are the go-to spot for "How Do I Fetch Data From This Collection" and, IMO, are the most intuitive accessor to any collection.
I always prefer to just use a single column ID column even if there is a composite key that can be used. I would just add an identity column to the table and use that for look up instead. Also, it would be faster because query for a single int column would perform better than a key spanned across three text columns.
Having a user maintain some sort of line index to look up a line doesn't seem very good to me. So if I had to pick between the two options you posed though, I would use the composite key.
If the client is retrieving the Line object using three string values, then that's what you pass to the getter method. From that point on, everything necessary to update the object in the database (such as a unique row ID) should be hidden within the Line object itself.
That way all the gory details are hidden from the client, which protects the client from damaging it, and also protects the client from any future changes you might make to the dB access within the Line object.