Here is a custom wrapper I made for System.Data.Linq. It contains a find method, so instead of your code:
var myContext = new DataContext();
var product = context.Products.Where(p => p.Id == productId).SingleOrDefault();
you can do this
var myContext = new DataContext();
var product = context.Products.Find(productId); //(assuming productId is your primary key)
You can grab the code below and do any custom modifications you wish to set product.Context, but this is an example of modifying the DataContext.
I also made save and delete methods. You'll notice I go out a regrab the record even though it is being passed in. I do this because the record might get detached from the context and not update. If anyone would like the full code I can post the github link.
public abstract class DbContext : IDisposable
{
#region Properties
private string _connectionString { get; set; }
private DataContext _context { get; set; }
#endregion
#region Constructor
public DbContext(string connectionString)
{
_connectionString = connectionString;
_context = new DataContext(_connectionString);
Initialized(_context);
}
public DbContext(string server, string database, string userID, string password)
{
_connectionString = string.Format(
"Server={0};Database={1};User Id={2};Password={3};MultipleActiveResultSets=true",
server,
database,
userID,
password);
_context = new DataContext(_connectionString);
Initialized(_context);
}
#endregion
#region Methods
/// <summary>
/// Is used to get the contents of a Sql Server Table.
/// </summary>
/// <typeparam name="TEntity">Type</typeparam>
/// <returns>Table</returns>
public Table<TEntity> GetTable<TEntity, TPKType>()
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
return _context.GetTable<TEntity>();
}
/// <summary>
/// Is used to get the contents of a Sql Server Table.
/// </summary>
/// <typeparam name="TEntity">Type</typeparam>
/// <returns>Table</returns>
public Table<TEntity> GetTable<TEntity>()
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
return GetTable<TEntity, long>();
}
protected virtual void Initialized(DataContext context) { }
/// <summary>
/// Saves the changes to the database. In order to save the table must inherit from DbTableEquatable
/// and be a type of IDbTableEquatable and the Primary Key Type must be a C# Structure
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <typeparam name="TPKType">Primary Key Type</typeparam>
/// <param name="entity">Record</param>
public virtual void SaveChanges<TEntity, TPKType>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
var changedList = _context.GetTable<TEntity>();
var ID = entity.GetType().GetProperty("ID").GetValue(entity);
_preprocessSave<TEntity, TPKType>(entity);
// Save changes
if (Convert.ToInt64(ID) == 0)
{
// Insert
// If No ID we need to insert on submit
_context.GetTable<TEntity>().InsertOnSubmit((TEntity)entity);
_context.SubmitChanges();
}
else
{
// Update
var item = changedList.Where(w => w.Equals(entity)).FirstOrDefault();
ReflectionManager.SetValuesWithSkip(entity, item, "ID");
_context.SubmitChanges();
}
Refresh();
}
/// <summary>
/// Saves the changes to the database. In order to save the Table the Record is from must inherit from DbTableEquatable
/// and be a type of IDbTableEquatable and the Primary Key Type must be a C# Structure
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <param name="entity">Record</param>
public virtual void SaveChanges<TEntity>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
SaveChanges<TEntity, long>(entity);
}
/// <summary>
/// Saves any non committed changes to the database
/// </summary>
public void SaveChanges()
{
_context.SubmitChanges();
Refresh();
}
/// <summary>
/// Marks the record as delete and will be deleted when saved
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <typeparam name="TPKType">Primary Key Type</typeparam>
/// <param name="entity">Record</param>
public virtual void DeleteOnSave<TEntity, TPKType>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
var item = _context.GetTable<TEntity>().Where(w => w.Equals(entity)).FirstOrDefault();
_context.GetTable<TEntity>().DeleteOnSubmit((TEntity)item);
}
/// <summary>
/// Marks the record as delete and will be deleted when saved
/// </summary>
/// <typeparam name="TEntity">Record Type</typeparam>
/// <param name="entity">Record</param>
public virtual void DeleteOnSave<TEntity>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
DeleteOnSave<TEntity, long>(entity);
}
protected virtual void _preprocessSave<TEntity, TPKType>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
}
protected virtual void _preprocessSave<TEntity>(TEntity entity)
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
_preprocessSave<TEntity, long>(entity);
}
public void Dispose()
{
_connectionString = "";
_context.Dispose();
_context = null;
}
public virtual void Refresh<TEntity>(RefreshMode mode, TEntity entity) where TEntity : class
{
_context.Refresh(RefreshMode.OverwriteCurrentValues, entity);
}
public virtual void Refresh()
{
_context = new DataContext(_connectionString);
}
public virtual void Refresh<TEntity>(RefreshMode mode, params TEntity[] entities) where TEntity : class
{
_context.Refresh(RefreshMode.OverwriteCurrentValues, entities);
}
public virtual void Refresh<TEntity>(RefreshMode mode, IEnumerable<TEntity> entities) where TEntity : class
{
_context.Refresh(RefreshMode.OverwriteCurrentValues, entities);
}
#endregion
}
Extenstions
public static class Extension
{
public static TEntity Find<TEntity, TPKType>(this Table<TEntity> table, TPKType ID, string pkName = "ID")
where TEntity : DbTableEquatable<IDbTableEquatable<TPKType>>
where TPKType : struct
{
TEntity copy = Activator.CreateInstance<TEntity>();
// set value through reflection
copy.GetType().GetProperty(pkName).SetValue(copy, ID, null);
return (TEntity)table.Where(w => w.Equals(copy)).FirstOrDefault();
}
public static TEntity Find<TEntity>(this Table<TEntity> table, long ID, string pkName = "ID")
where TEntity : DbTableEquatable<IDbTableEquatable<long>>
{
TEntity copy = Activator.CreateInstance<TEntity>();
// set value through reflection
copy.GetType().GetProperty(pkName).SetValue(copy, ID, null);
return (TEntity)table.Where(w => w.Equals(copy)).FirstOrDefault();
}
}
}
Interface/Abstraction
/// <summary>
/// This Class Assumes the type T has a property called ID. MUST be
/// used with IDbEquatable
/// </summary>
/// <typeparam name="T">Class Type</typeparam>
public abstract class DbTableEquatable<T> : IEquatable<T> where T : class
{
public bool Equals(T other)
{
//Check whether the compared object is null.
if (Object.ReferenceEquals(other, null))
{
return false;
}
//Check whether the compared object references the same data.
if (Object.ReferenceEquals(this, other))
{
return true;
}
return ((dynamic)other).ID == ((dynamic)this).ID;
}
}
/// <summary>
/// Needs to be inherited from in order for Ion.Data.Linq functions to work
/// </summary>
/// <typeparam name="T">Primary Key Type</typeparam>
public interface IDbTableEquatable<T>
{
T ID { get; set; }
}
here is a table implementation
[Table(Name = "Crews")]
public class Crew : DbTableEquatable<IDbTableEquatable<long>>, IDbTableEquatable<long>
{
[Column(IsPrimaryKey = true, DbType = "Bigint NOT NULL IDENTITY", AutoSync = AutoSync.OnInsert, IsDbGenerated = true)]
public long ID { get; set; }
[Column]
public string Alias { get; set; }
[Column]
public string DefaultForeground { get; set; }
[Column]
public string DefaultBackground { get; set; }
[Column]
public string AccountEmailAddress { get; set; }
[Column]
public long? CrewLeaderEmployeeID { get; set; }
[Column]
public string Comments { get; set; }
[Column]
public string Password { get; set; }
[Column]
public string PrivateICSLink { get; set; }
[Column]
public string PrivateXMLLink { get; set; }
}