This class allows the definition of a CRUD to a linq datacontext and entity in one line that has all the DataAnnotations completed so that ObjectDataSource etc can pick up the class and Insert/Delete/etc methods.
Once included in your code you can define a CRUD for an entity in a datacontext like so
public class MyDataDAL : GenericLinqDAL<TheDataContextTypeName, TheEntityTypeName> { //yes that is it }
Here it is (it's a biggy and a few extensions afterwards + SortableList (and extension to List that can be automatically sorted)
Grab source from source forge http://sourceforge.net/projects/genericlinqdals/
GenericLinqDAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;
using System.Data.Linq;
using System.Reflection;
using System.Data.Linq.Mapping;
namespace Icst
{
[DataObject]
public partial class GenericLinqDAL<TContext, TEntity>
where TContext : DataContext, new()
where TEntity : class, new()
{
protected TContext Db = new TContext();
PropertyInfo objectKey;
#region ctor
public GenericLinqDAL()
{
objectKey = GetPrimaryKey<TEntity>();
if (objectKey == null) throw new ArgumentException(String.Format("The Linq class doesn't have a primary key. You must specify a field you want to use as the key in the constructor"));
}
public GenericLinqDAL(string keyPropertyName)
{
objectKey = GetPrimaryKey<TEntity>(keyPropertyName);
if (objectKey == null) throw new ArgumentException(String.Format("The Linq class does not have a property: {0}", keyPropertyName));
}
public static PropertyInfo GetPrimaryKey<TEntity>(string keyPropertyName)
{
PropertyInfo[] infos = typeof(TEntity).GetProperties();
foreach (PropertyInfo info in infos)
{
if (info.Name.Equals(keyPropertyName)) return info;
}
return null;
}
public static PropertyInfo GetPrimaryKey<TEntity>()
{
PropertyInfo[] infos = typeof(TEntity).GetProperties();
PropertyInfo PKProperty = null;
foreach (PropertyInfo info in infos)
{
var propsWithColAttr = info.GetCustomAttributes(false).Where(x => x.GetType() == typeof(ColumnAttribute));
var column = propsWithColAttr.FirstOrDefault(x => ((ColumnAttribute)x).IsPrimaryKey && ((ColumnAttribute)x).DbType.Contains("NOT NULL"));
if (column != null)
{
PKProperty = info;
break;
}
}
if (PKProperty == null)
{
throw new NotSupportedException(
typeof(TEntity).ToString() + " has no Primary Key");
}
return PKProperty;
}
#endregion
#region C
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Insert, true)]
public virtual void CreateDataObject(TEntity w)
{
Db.GetTable<TEntity>().InsertOnSubmit(w);
Save();
}
#endregion
#region R
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, false)]
public virtual TEntity ReadDataObject(object key)
{
return Db.GetTable<TEntity>()
.Single(
delegate(TEntity e)
{
object currKey = GetDataObjectKeyValue(e);
return currKey.ToString().Equals(key.ToString());
}
);
}
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, true)]
public virtual SortableList<TEntity> ReadDataObjects()
{
return Db.GetTable<TEntity>().AsEnumerable().ToSortableList();
}
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, true)]
public virtual SortableList<TEntity> ReadDataObjects(string sortExpression, bool sortAscending)
{
if (!String.IsNullOrEmpty(sortExpression))
{
var data = Db.GetTable<TEntity>().AsEnumerable().ToSortableList();
data.Sort(sortExpression, sortAscending);
return data;
}
return ReadDataObjects();
}
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, true)]
public virtual SortableList<TEntity> ReadDataObjects(string sortExpression, bool sortAscending, int maximumRows, int startRowIndex)
{
var data = ReadDataObjects(sortExpression, sortAscending).Skip(startRowIndex).Take(maximumRows).ToSortableList();
return data;
}
#endregion
#region U
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Update, true)]
public virtual void UpdateDataObject(TEntity e)
{
var result = ReadDataObject(GetDataObjectKeyValue(e));
e.CopyTo(result);
Save();
}
#endregion
#region D
[System.ComponentModel.DataObjectMethod(DataObjectMethodType.Delete, true)]
public virtual void DeleteDataObject(TEntity e)
{
var result = ReadDataObject(GetDataObjectKeyValue(e));
Db.GetTable<TEntity>().DeleteOnSubmit(result);
Save();
}
#endregion
#region Utils
public virtual int RowCount()
{
return ReadDataObjects().Count();
}
public virtual int RowCount(string sortExpression, bool sortAscending)
{
return ReadDataObjects().Count();
}
protected void Save()
{
Db.SubmitChanges();
}
private object GetDataObjectKeyValue(TEntity e)
{
return e.GetType().GetProperty(objectKey.Name).GetValue(e, null);
}
#endregion
}
}
ExtensionMethods
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Icst
{
public static class Extensions
{
public static void CopyTo(this object S, object T)
{
foreach (var pS in S.GetType().GetProperties())
{
foreach (var pT in T.GetType().GetProperties())
{
if (pT.Name != pS.Name) continue;
(pT.GetSetMethod()).Invoke(T, new object[] { pS.GetGetMethod().Invoke(S, null) });
}
};
}
public static SortableList<TSource> ToSortableList<TSource>(this IEnumerable<TSource> source)
{
SortableList<TSource> sortList = new SortableList<TSource>();
foreach (TSource item in source)
{
sortList.Add(item);
}
return sortList;
}
}
}
SortableList.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
namespace Icst
{
public class SortableList<T> : List<T>
{
private string _propertyName;
private bool _ascending;
public void Sort(string propertyName, bool ascending)
{
if (_propertyName == propertyName && _ascending == ascending)
{
_ascending = !ascending;
}
else
{
_propertyName = propertyName;
_ascending = ascending;
}
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
PropertyDescriptor propertyDesc = properties.Find(propertyName, true);
PropertyComparer<T> pc = new PropertyComparer<T>(propertyDesc,(_ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending);
this.Sort(pc);
}
}
public class PropertyComparer<T> : System.Collections.Generic.IComparer<T>
{
// The following code contains code implemented by Rockford Lhotka:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet01272004.asp
private PropertyDescriptor _property;
private ListSortDirection _direction;
public PropertyComparer(PropertyDescriptor property, ListSortDirection direction)
{
_property = property;
_direction = direction;
}
public int Compare(T xWord, T yWord)
{
// Get property values
object xValue = GetPropertyValue(xWord, _property.Name);
object yValue = GetPropertyValue(yWord, _property.Name);
// Determine sort order
if (_direction == ListSortDirection.Ascending)
{
return CompareAscending(xValue, yValue);
}
else
{
return CompareDescending(xValue, yValue);
}
}
public bool Equals(T xWord, T yWord)
{
return xWord.Equals(yWord);
}
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
// Compare two property values of any type
private int CompareAscending(object xValue, object yValue)
{
int result;
if (xValue == null && yValue != null) return -1;
if (yValue == null && xValue != null) return 1;
if (xValue == null && yValue == null) return 0;
// If values implement IComparer
if (xValue is IComparable)
{
result = ((IComparable)xValue).CompareTo(yValue);
}
// If values don't implement IComparer but are equivalent
else if (xValue.Equals(yValue))
{
result = 0;
}
// Values don't implement IComparer and are not equivalent, so compare as string values
else result = xValue.ToString().CompareTo(yValue.ToString());
// Return result
return result;
}
private int CompareDescending(object xValue, object yValue)
{
// Return result adjusted for ascending or descending sort order ie
// multiplied by 1 for ascending or -1 for descending
return CompareAscending(xValue, yValue) * -1;
}
private object GetPropertyValue(T value, string property)
{
// Get property
PropertyInfo propertyInfo = value.GetType().GetProperty(property);
// Return value
return propertyInfo.GetValue(value, null);
}
}
}
PLEASE mark answers that actually work as answer (found above the post) and try to post code where possible.
luappy13
Participant
1874 Points
408 Posts
Generic LINQ CRUD with SortableList algorithm all data annotated ready for point click designer s...
Jul 04, 2011 08:11 PM|LINK
Okay here's a class I find quite useful.
This class allows the definition of a CRUD to a linq datacontext and entity in one line that has all the DataAnnotations completed so that ObjectDataSource etc can pick up the class and Insert/Delete/etc methods.
Once included in your code you can define a CRUD for an entity in a datacontext like so
public class MyDataDAL : GenericLinqDAL<TheDataContextTypeName, TheEntityTypeName> { //yes that is it }Here it is (it's a biggy and a few extensions afterwards + SortableList (and extension to List that can be automatically sorted)
Grab source from source forge http://sourceforge.net/projects/genericlinqdals/
GenericLinqDAL.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel; using System.Data.Linq; using System.Reflection; using System.Data.Linq.Mapping; namespace Icst { [DataObject] public partial class GenericLinqDAL<TContext, TEntity> where TContext : DataContext, new() where TEntity : class, new() { protected TContext Db = new TContext(); PropertyInfo objectKey; #region ctor public GenericLinqDAL() { objectKey = GetPrimaryKey<TEntity>(); if (objectKey == null) throw new ArgumentException(String.Format("The Linq class doesn't have a primary key. You must specify a field you want to use as the key in the constructor")); } public GenericLinqDAL(string keyPropertyName) { objectKey = GetPrimaryKey<TEntity>(keyPropertyName); if (objectKey == null) throw new ArgumentException(String.Format("The Linq class does not have a property: {0}", keyPropertyName)); } public static PropertyInfo GetPrimaryKey<TEntity>(string keyPropertyName) { PropertyInfo[] infos = typeof(TEntity).GetProperties(); foreach (PropertyInfo info in infos) { if (info.Name.Equals(keyPropertyName)) return info; } return null; } public static PropertyInfo GetPrimaryKey<TEntity>() { PropertyInfo[] infos = typeof(TEntity).GetProperties(); PropertyInfo PKProperty = null; foreach (PropertyInfo info in infos) { var propsWithColAttr = info.GetCustomAttributes(false).Where(x => x.GetType() == typeof(ColumnAttribute)); var column = propsWithColAttr.FirstOrDefault(x => ((ColumnAttribute)x).IsPrimaryKey && ((ColumnAttribute)x).DbType.Contains("NOT NULL")); if (column != null) { PKProperty = info; break; } } if (PKProperty == null) { throw new NotSupportedException( typeof(TEntity).ToString() + " has no Primary Key"); } return PKProperty; } #endregion #region C [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Insert, true)] public virtual void CreateDataObject(TEntity w) { Db.GetTable<TEntity>().InsertOnSubmit(w); Save(); } #endregion #region R [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, false)] public virtual TEntity ReadDataObject(object key) { return Db.GetTable<TEntity>() .Single( delegate(TEntity e) { object currKey = GetDataObjectKeyValue(e); return currKey.ToString().Equals(key.ToString()); } ); } [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, true)] public virtual SortableList<TEntity> ReadDataObjects() { return Db.GetTable<TEntity>().AsEnumerable().ToSortableList(); } [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, true)] public virtual SortableList<TEntity> ReadDataObjects(string sortExpression, bool sortAscending) { if (!String.IsNullOrEmpty(sortExpression)) { var data = Db.GetTable<TEntity>().AsEnumerable().ToSortableList(); data.Sort(sortExpression, sortAscending); return data; } return ReadDataObjects(); } [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Select, true)] public virtual SortableList<TEntity> ReadDataObjects(string sortExpression, bool sortAscending, int maximumRows, int startRowIndex) { var data = ReadDataObjects(sortExpression, sortAscending).Skip(startRowIndex).Take(maximumRows).ToSortableList(); return data; } #endregion #region U [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Update, true)] public virtual void UpdateDataObject(TEntity e) { var result = ReadDataObject(GetDataObjectKeyValue(e)); e.CopyTo(result); Save(); } #endregion #region D [System.ComponentModel.DataObjectMethod(DataObjectMethodType.Delete, true)] public virtual void DeleteDataObject(TEntity e) { var result = ReadDataObject(GetDataObjectKeyValue(e)); Db.GetTable<TEntity>().DeleteOnSubmit(result); Save(); } #endregion #region Utils public virtual int RowCount() { return ReadDataObjects().Count(); } public virtual int RowCount(string sortExpression, bool sortAscending) { return ReadDataObjects().Count(); } protected void Save() { Db.SubmitChanges(); } private object GetDataObjectKeyValue(TEntity e) { return e.GetType().GetProperty(objectKey.Name).GetValue(e, null); } #endregion } }ExtensionMethods
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Icst { public static class Extensions { public static void CopyTo(this object S, object T) { foreach (var pS in S.GetType().GetProperties()) { foreach (var pT in T.GetType().GetProperties()) { if (pT.Name != pS.Name) continue; (pT.GetSetMethod()).Invoke(T, new object[] { pS.GetGetMethod().Invoke(S, null) }); } }; } public static SortableList<TSource> ToSortableList<TSource>(this IEnumerable<TSource> source) { SortableList<TSource> sortList = new SortableList<TSource>(); foreach (TSource item in source) { sortList.Add(item); } return sortList; } } }SortableList.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.Reflection; namespace Icst { public class SortableList<T> : List<T> { private string _propertyName; private bool _ascending; public void Sort(string propertyName, bool ascending) { if (_propertyName == propertyName && _ascending == ascending) { _ascending = !ascending; } else { _propertyName = propertyName; _ascending = ascending; } PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T)); PropertyDescriptor propertyDesc = properties.Find(propertyName, true); PropertyComparer<T> pc = new PropertyComparer<T>(propertyDesc,(_ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending); this.Sort(pc); } } public class PropertyComparer<T> : System.Collections.Generic.IComparer<T> { // The following code contains code implemented by Rockford Lhotka: // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet01272004.asp private PropertyDescriptor _property; private ListSortDirection _direction; public PropertyComparer(PropertyDescriptor property, ListSortDirection direction) { _property = property; _direction = direction; } public int Compare(T xWord, T yWord) { // Get property values object xValue = GetPropertyValue(xWord, _property.Name); object yValue = GetPropertyValue(yWord, _property.Name); // Determine sort order if (_direction == ListSortDirection.Ascending) { return CompareAscending(xValue, yValue); } else { return CompareDescending(xValue, yValue); } } public bool Equals(T xWord, T yWord) { return xWord.Equals(yWord); } public int GetHashCode(T obj) { return obj.GetHashCode(); } // Compare two property values of any type private int CompareAscending(object xValue, object yValue) { int result; if (xValue == null && yValue != null) return -1; if (yValue == null && xValue != null) return 1; if (xValue == null && yValue == null) return 0; // If values implement IComparer if (xValue is IComparable) { result = ((IComparable)xValue).CompareTo(yValue); } // If values don't implement IComparer but are equivalent else if (xValue.Equals(yValue)) { result = 0; } // Values don't implement IComparer and are not equivalent, so compare as string values else result = xValue.ToString().CompareTo(yValue.ToString()); // Return result return result; } private int CompareDescending(object xValue, object yValue) { // Return result adjusted for ascending or descending sort order ie // multiplied by 1 for ascending or -1 for descending return CompareAscending(xValue, yValue) * -1; } private object GetPropertyValue(T value, string property) { // Get property PropertyInfo propertyInfo = value.GetType().GetProperty(property); // Return value return propertyInfo.GetValue(value, null); } } }