LINQ To SQL Generic methods
In order to avoid too much coding in my DAO layer, I've been creating some generic LINQ to SQL CRUD methods.
Generic Delete method:
/// <summary>
/// Delete an entity
/// </summary>
/// <param name="entity">Entity to be deleted</param>
[System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Delete)]
public void Delete(TEntity entity)
{
try
{
TEntity original = GetEntity(_getPrimaryKey().GetValue(entity, null));
DAODataContext.GetTable<TEntity>().DeleteOnSubmit(original);
}
catch (Exception e)
{
throw new DAOException(DAOException.EError.Delete, e);
}
}
Generic Attach method:
The generic attach method is used to attach existing entitie or new entitie, a test is executed to check if the entitie has to be inserted or updated:
/// <summary>
/// Attach an entity to the data context
/// If the entity is allready attached, exception is catched
/// </summary>
/// <param name="entity">Entity to attach</param>
public void Attach(TEntity entity)
{
PropertyInfo primaryKey = _getPrimaryKey();
if (_isNullOrEmpty(primaryKey.GetValue(entity, null)))
{
//new object case
DAODataContext.GetTable<TEntity>().InsertOnSubmit(entity);
}
else
{
try
{
//existing object case
DAODataContext.GetTable<TEntity>().Attach(entity);
}
catch (InvalidOperationException)
{
// Do nothing for exception when object already attached to data context
}
catch (Exception e)
{
throw new DAOException(DAOException.EError.Attach, e);
}
}
}
Method to get the primary key of an entitie:
/// <summary>
/// Gets the primary key of the current entity type
/// </summary>
/// <returns>Primary key property info</returns>
private PropertyInfo _getPrimaryKey()
{
MetaTable mapping = DAODataContext.Mapping.GetTable(typeof(TEntity));
MetaDataMember pkfield = mapping.RowType.DataMembers.SingleOrDefault(d => d.IsPrimaryKey);
int count = mapping.RowType.DataMembers.Count(d => d.IsPrimaryKey);
if (count < 1) throw new Exception(String.Format("Table {0} does not contain a Primary Key field", mapping.TableName));
if (count > 1) throw new Exception(String.Format("Table {0} contains a composite primary key field", mapping.TableName));
return typeof(TEntity).GetProperty(pkfield.MappedName);
}
Method to test if a field as a null value:
/// <summary>
/// Check if a type object is considered as null value depending on its type
/// (<1 for int , Guid.Empty for Guid, null or empty for string)
/// </summary>
/// <param name="value">Value to be check</param>
/// <returns>True if value is considered null</returns>
private bool _isNullOrEmpty(object value)
{
if (value is int)
{
return (int)value < 1;
}
else if (value is Guid)
{
return value == null || (Guid)value == Guid.Empty;
}
else if (value is string)
{
return string.IsNullOrEmpty((string)value);
}
return false;
}
Generic Get an Entitie method:
/// <summary>
/// Generic search method to get one entity, loading child objects requested by the loadOptionPredicates
/// </summary>
/// <param name="loadOptions">Request to load child objects</param>
/// <param name="predicate">Predicate to search for the entity</param>
/// <returns>A found entity with child entities or a default value</returns>
[System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
public TEntity FindEntity(DataLoadOptions loadOptions, Expression<Func<TEntity, bool>> predicate)
{
TEntity res = null;
try
{
if (loadOptions != null)
{
if (DAODataContext.DeferredLoadingEnabled == true)
DAODataContext.DeferredLoadingEnabled = false;
DAODataContext.LoadOptions = loadOptions;
}
res = DAODataContext.GetTable<TEntity>().FirstOrDefault(predicate);
}
catch (Exception e)
{
throw new DAOException(DAOException.EError.FindEntitie, e);
}
return res;
}
Generic New method:
/// <summary> /// Returns a new attached instance the requested Entity with default values /// </summary> /// <returns></returns> public TEntity New() { TEntity newEntity = new TEntity(); Attach(newEntity); return newEntity; }