So I have a Winforms program that is set up such that There is a single form with a datagridview that is responsible for displaying Litigation Matters. A matter is just a class that contains an ID, Description, some Dates, and then some Collections (Navigation properties) eg:
public int MatterID
public string Description
public DateTime? DateFiled
public ICollection<Contact> Plaintiffs
public ICollection<Contact> Attorneys
Now here is where the problem starts:
The user can view different sets of Matters; All Matters, Open Matters, Closed Matters, Searched Matters (based on search criteria), Matters associated with a given contact, etc (many more)
This MatterViewer form has a datagridview that is responsible for displaying the matters and refreshing the data as things get updated. (eg. A user could right click on a Matter in the datagridview and edit it, then the Matters in the Datagridview need to be refreshed).
In order for this to work, I currently have form constructors that take in a querystring so that I have access to the query that was used to obtain these specific matters and use it to refresh the specific data as needed:
public FormViewMatters(string matterQueryString, string dataSetName = null)
{
//Code here
}
If I were to pass in just a list of Matters to the Form, then I would only ever be able to refresh items in that list, not refresh the all potential matters based on the query.
Using the querystring however, limits me to lazy loading navigation properties. I currently need to eager load some of the properties and I am unable to do so.
So what is the best approach to go about refreshing specific data in general (including navigation properties)?
Related
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;
}
I have the following data and objects in my program.
A DynamicObjectContainer that contains the following objects.
MeasurementParameters : DataContainer (DataContainer is the base class)
This MeasurementParameters object has many public properties, whose names I know only during runtime. I have also set up internal wiring in the DataContainer base class such that, I can access the values of the properties contained in the MeasurementParameters class using an easy to use interface.
Ex : Say I have a property in MeasurementParameters named as "pumpspeed" (type string). I can access the value of that property using this function.
MeasurementParameters.GetStringValue("pumpspeed");
I have achieved this by creating lists of delegates internally in the DataContainer object using reflection during construction of the object. (This is a one time thing.)
So far so good.
Now I am stuck at the point where I want to display these values within MeasurementParameters in a windows form.
Since I only know the property names at runtime, I have to provide the user with some method to map the property names (defined only by him in a script file) to the fixed labels within the form. So the user saves the mapping data to the table in the following format.
Entry : "pumpspeed" "label22"
I want a fast and efficient method to fetch this mapping from the database, fetch required data from the MeasuremetParameters object and display it in the windows form.
NOTE : If this is a one time operation, I have many solutions. The problem is two fold.
There are a huge number of properties in the MeasurementParameters (at around 200)
The MeasurementParameters object contains functions that update it's properties continuously. SO My windows form has to call those functions to update the MeasurementParameters object data, fetch the data and display it in the correct labels.
ALSO, this should happen in cycles of around 2 -3 times a second. (ideally)
Can anyone help me in architecting a solution for this?? A general object structure and relationship advice will also be helpful to me.
I can post the code I am using if required.
Not seeing a huge problem here
So you have Table ObjectID, PropertyName, ControlName
On opening the form / selecting the object, query them out
Build a Dictionary Keyed by PropertyName with a Value of the Label (looked up by the name of teh control from the query MyForm.Controls.FindByName(Somename). Add an OnPropertyChangedEvent to your class that throws up the name of the Property in event args then add a handler on the form
Mappings[e.PropertyName].Text = Object[e.PropertyName].GetStringValue;
Might have to twidlle with it to deal with say display controls that aren't Labels, or Panels on the Form, but it should just batter away.
I have a DropDownList control which is databound via a SqlDataSource whose query returns 3 fields (Label, Value, and Active) - Is there a way to access the databound dataset programatically to check whether the Active flag is true or false?
I know that this can be done DURING the databind, but I need the Active flag to checked during PreRender phase as the control may need to select a value where Active=false if loading an old record where this selection had been made. (During PreRender, I'm removing all Active=false items, unless it's the value that I'm setting the DropDownList to).
I have this working perfectly by populating a DataView with a SqlDataSource. Select and comparing/removing items based on this, but hitting the database twice to get this info a second time for each control seems inefficient.
Also, I can't write a piece of reusable/generic code for all controls as my current method only works when the SqlDataSource doesn't require any SelectArguments. If I can access the databound data directly, this would bypass this problem too.
Any advice is much appreciated!
I think the main problem you're having comes from using a SqlDataSource as your data-access. SqlDataSources are easy to set up and give you instant results, but they are extremely inflexible and require reuse across pages.
I would create a function that grabs the data from the database and stores it in an List or IEnumerable. If the data is in a List then you have access to it programmatically and validation is much easier to achieve.
Here is a sample below that uses the Entity Framework to access the database
Mark up
<asp:DropDownList ID="ddlTest" runat="server"></asp>
Code Behind
public List<Record> GetAllRecordsByUserName(string credentials)
{
List<Record> recordList;
using (CustomEntities context = new CustomEntities())
{
IQueryable<Record> recordQuery = from records in context.Records
where records.UserName == credentials
select records;
recordList = recordQuery.ToList<Record>();
}
return recordList;
}
public void ValidateAndBind(string username)
{
List<Record> recordList = GetAllRecordsByUserName(username);
// Do validation here
ddlTest.DataSource = recordList;
ddlTest.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
ValidateAndBind("test.username");
}
You can use whatever data-access method you desire, but setting it programmatically allows you to reuse it across pages. In the methods above I created it in the page for terms of space. In practice, you should create a class that handles specific data retrieval, which is usually called a Data Access Layer.
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();
}
}