I have two classes OrderInfo and OrderManager and I would like to implement sorting in the GridView or in general without using an ObjectDataSource.
I would like to have a method in the OrderManager called Sort or write a Sort class that has a variety of sort methods (Bubble Sort etc.) that I can call to sort the columns in the GridView. Or sort any data in my project for that matter.
Is there a sleek way of doing this in C# 2.0 Using Generics, anonymous methods etc.
OrderManager Class
#region using directives
using System;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Text;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Model;
#endregion
namespace BLL
{
/// <summary>
/// Used to manage orders.
/// </summary>
public class OrderManager
{
#region Constructors
/// <summary>
/// Default Constructor for OrderManager.
/// This is required to serialize the class.
/// </summary>
public OrderManager()
{
}
#endregion
#region public Methods
/// <summary>
/// Gets an order by order ID.
/// </summary>
/// <param name="orderID"></param>
/// <returns>An order by order ID.</returns>
public static OrderInfo GetOrder(int orderID)
{
//Create a default database instance.
Database db = DatabaseFactory.CreateDatabase();
//Name of Stored Procedure.
string sqlCommand = "OrderGetByID";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
//Create a parameter.
db.AddInParameter(dbCommand, "OrderID", DbType.Int32, orderID);
//Invoke a SQL command.
using (IDataReader dataReader = db.ExecuteReader(dbCommand))
{
OrderInfo order = null;
while (dataReader != null && dataReader.Read())
{
order = new OrderInfo(dataReader);
}
if (dataReader != null)
{
dataReader.Close();
}
//Return an Order.
return order;
}
}
/// <summary>
/// Gets a generic collection of Orders.
/// </summary>
/// <returns>A generic collection of Orders.</returns>
public static Collection<OrderInfo> GetOrders()
{
//Create a default database instance.
Database db = DatabaseFactory.CreateDatabase();
//Invoke a SQL command.
using (IDataReader dataReader = db.ExecuteReader(CommandType.StoredProcedure, "OrdersGetAll"))
{
Collection<OrderInfo> orders = new Collection<OrderInfo>();
OrderInfo order = null;
while (dataReader != null && dataReader.Read())
{
order = new OrderInfo(dataReader);
//Add an order to the orders collection.
orders.Add(order);
}
if (dataReader != null)
{
dataReader.Close();
}
//Return a generic collection of Orders.
return orders;
}
}
/// <summary>
/// Deletes an Order by OrderID.
/// </summary>
/// <param name="OrderID">The OrderID of the Order to Delete.</param>
/// <returns>Whether the method succeeds or not.</returns>
public static bool Delete(OrderInfo order)
{
//Create a default database instance.
Database db = DatabaseFactory.CreateDatabase();
string sqlCommand = "OrderDelete";
//Name of Stored Procedure.
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
int orderID = order.OrderID;
if (orderID > 0)
{
//Create a parameter.
db.AddInParameter(dbCommand, "OrderID", DbType.Int32, orderID);
//Invoke a SQL command and return true if deletion is successful.
return db.ExecuteNonQuery(dbCommand) == 1 true : false;
}
return false;
}
/// <summary>
/// Save Method checks if the record needs to be inserted or updated.
/// </summary>
/// <param name="order"></param>
/// <returns>Whether the method succeeds or not.</returns>
public static bool Save(OrderInfo order)
{
if (order != null)
{
if (order.OrderID == 0)
{
return Insert(order);
}
else if (order.OrderID > 0)
{
return Update(order);
}
else
{
return false;
}
}
return false;
}
#endregion
#region private Methods
/// <summary>
/// Insert Method saves a new order record called from the Save method.
/// </summary>
/// <param name="order"></param>
/// <returns>Whether the method succeeds or not.</returns>
private static bool Insert(OrderInfo order)
{
int orderID = 0;
//Create a default database instance.
Database db = DatabaseFactory.CreateDatabase();
orderID = Convert.ToInt32(db.ExecuteScalar("OrderInsert",
order.CustomerID,
order.EmployeeID,
order.OrderDate,
order.RequiredDate,
order.ShippedDate,
order.ShipVia,
order.Freight,
order.ShipName,
order.ShipAddress,
order.ShipCity,
order.ShipRegion,
order.ShipPostalCode,
order.ShipCountry));
return (orderID > 0);
}
/// <summary>
/// Update method changes existing record with new order info called from the save method.
/// </summary>
/// <param name="order"></param>
/// <returns>Whether the method succeeds or not.</returns>
private static bool Update(OrderInfo order)
{
//Create a default database instance.
Database db = DatabaseFactory.CreateDatabase();
db.ExecuteNonQuery("OrderUpdate",
order.OrderID,
order.CustomerID,
order.EmployeeID,
order.OrderDate,
order.RequiredDate,
order.ShippedDate,
order.ShipVia,
order.Freight,
order.ShipName,
order.ShipAddress,
order.ShipCity,
order.ShipRegion,
order.ShipPostalCode,
order.ShipCountry);
return true;
}
#endregion
}
}
OrderInfo Class
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
namespace Model
{
/// <summary>
/// OrderInfo is used to model an order.
/// </summary>
[Serializable]
public class OrderInfo
{
#region Internal member variables and properties
private int _orderID;
public int OrderID
{
get { return _orderID; }
set { _orderID = value; }
}
private string _customerID;
public string CustomerID
{
get { return _customerID; }
set { _customerID = value; }
}
private int _employeeID;
public int EmployeeID
{
get { return _employeeID; }
set { _employeeID = value; }
}
private DateTime _orderDate;
public DateTime OrderDate
{
get { return _orderDate; }
set { _orderDate = value; }
}
private DateTime _requiredDate;
public DateTime RequiredDate
{
get { return _requiredDate; }
set { _requiredDate = value; }
}
private DateTime _shippedDate;
public DateTime ShippedDate
{
get { return _shippedDate; }
set { _shippedDate = value; }
}
private int _shipVia;
public int ShipVia
{
get { return _shipVia; }
set { _shipVia = value; }
}
private decimal _freight;
public decimal Freight
{
get { return _freight; }
set { _freight = value; }
}
private string _shipName;
public string ShipName
{
get { return _shipName; }
set { _shipName = value; }
}
private string _shipAddress;
public string ShipAddress
{
get { return _shipAddress; }
set { _shipAddress = value; }
}
private string _shipCity;
public string ShipCity
{
get { return _shipCity; }
set { _shipCity = value; }
}
private string _shipRegion;
public string ShipRegion
{
get { return _shipRegion; }
set { _shipRegion = value; }
}
private string _shipPostalCode;
public string ShipPostalCode
{
get { return _shipPostalCode; }
set { _shipPostalCode = value; }
}
private string _shipCountry;
public string ShipCountry
{
get { return _shipCountry; }
set { _shipCountry = value; }
}
#endregion
#region Constructors
/// <summary>
/// Default Constructor for OrderInfo.
/// This is required to serialize the class.
/// </summary>
public OrderInfo()
{
}
/// <summary>
/// Constructor with specified initial values.
/// </summary>
/// <param name="dataReader"></param>
public OrderInfo(IDataReader dataReader)
{
//Populate internal fields with data from the order record.
this._orderID = dataReader.GetInt32(0);
if (!dataReader.IsDBNull(1))
{
this._customerID = dataReader.GetString(1);
}
if (!dataReader.IsDBNull(2))
{
this._employeeID = dataReader.GetInt32(2);
}
if (!dataReader.IsDBNull(3))
{
this._orderDate = dataReader.GetDateTime(3);
}
if (!dataReader.IsDBNull(4))
{
this._requiredDate = dataReader.GetDateTime(4);
}
if (!dataReader.IsDBNull(5))
{
this._shippedDate = dataReader.GetDateTime(5);
}
if (!dataReader.IsDBNull(6))
{
this._shipVia = dataReader.GetInt32(6);
}
if (!dataReader.IsDBNull(7))
{
this._freight = dataReader.GetDecimal(7);
}
if (!dataReader.IsDBNull(8))
{
this._shipName = dataReader.GetString(8);
}
if (!dataReader.IsDBNull(9))
{
this._shipAddress = dataReader.GetString(9);
}
if (!dataReader.IsDBNull(10))
{
this._shipCity = dataReader.GetString(10);
}
if (!dataReader.IsDBNull(11))
{
this._shipRegion = dataReader.GetString(11);
}
if (!dataReader.IsDBNull(12))
{
this._shipPostalCode = dataReader.GetString(12);
}
if (!dataReader.IsDBNull(13))
{
this._shipCountry = dataReader.GetString(13);
}
}
#endregion
}
}

Sorting in C#2.0 - GridView sorting without a XXXDataSource
pebelf
Hi Bruce, I have followed your tip but I'm still stuck. I have 2 classes OrderInfo and OrderManager. The OrderInfo class is the model of an Order and the OrderManager does all the work on the OrderInfo such as Insert, Update, Delete, Sort etc.
I’m trying to implement sorting and have the following code in the OrderManager class:
public static Collection<OrderInfo> Sort(string sortExpression, string sortDirection)
{
GenericComparer comparer = new GenericComparer();
comparer.SortExpression = sortExpression;
comparer.SortDirection = sortDirection;
call Compare method
//Return a sorted generic collection of Orders.
return orders;
}
private sealed class GenericComparer : IComparer<OrderInfo>
{
#region Internal member variables and properties
private string _sortExpression = string.Empty;
public string SortExpression
{
get { return _sortExpression; }
set { _sortExpression = value; }
}
private string _sortDirection = "Ascending";
public string SortDirection
{
get { return _sortDirection; }
set { _sortDirection = value; }
}
#endregion
public int Compare(OrderInfo o, OrderInfo oo)
{
OrderInfo order = o;
OrderInfo otherOrder = oo;
if (this.SortDirection.Equals("Ascending"))
{
return order. .CompareTo(otherOrder. );
}
else
{
return otherOrder. .CompareTo(order. );
}
}
}
First of all if this is a BS approach let me know. Otherwise here is the error I’m getting:
Error 1 'Model.OrderInfo' does not implement interface member 'System.IComparable<Model.OrderInfo>.CompareTo(Model.OrderInfo)' D:\Projects\ShareYourLoss\Model\OrderInfo.cs 11 18 Model
I don’t want to implement IComparable or ICompare in the OrderInfo. I want my OrderManager to do all the work and I want the GenericComparer to be flexible enough to sort any column passed in from a GridView for example. So it would be order. + SortExpression. So that I can sort by OrderID, ShipDate etc. depending which column is clicked. The code is not finished but I’m in over my head and don’t know how to finish it.
An even nicer solution would be to have a separate comparer class that is generic enough and could sort any collection of objects OrderInfo, CustomerInfo, ProductInfo etc. but I have no idea how to accomplish that.
Would anybody be kind enough and help newbie out
Thanks,
Edi
DBRGSS
Hope that helps.
Bruce Johnson [C# MVP]
http://www.objectsharp.com/blogs/bruce
Rick_H
You can provide data from any list, so all you need is to sort this list. You can use ArrayList, List<> or other collection class and write any own sort methods, but I think standard Sort() on default list implementations is good enough, at least they do not use bubble sort - this is really slow method, I think they use division by 2 sorting (quick sort).
P. S. If you use "using" for dataReader, then you do not need to call Close() manually, it will be called after using is completed.
FlyingHigh
Also you can use BindingSource in place of OrderManager - it has sorting features too.
Buble Sort is really slow method. Storing SortDirection in strings is really slow too (bool is much faster).
VDeepak
I think implementing own sorting is good idea for 2 purposes: get know what it takes to implement sorting and write sample application to demonstrate difference between sorting methods.