我想将一个ObservableCollection绑定到一个sql表,我想到的是将事件处理程序添加到集合中并跟踪事件类型以处理sql删除和插入操作,例如
someobservablecollection.CollectionChanged += (s, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
//Generate sql Insert command for e.NewItems using reflection
}
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
//Generate sql Delete command for e.OldItems
}
};
对于更新,我必须将事件处理程序添加到ViewModel中的Selected Object
我的问题是我是在正确的轨道上,是否已经完成过或者我必须从头开始做?
答案 0 :(得分:0)
这是我的解决方案
首先我创建了2个简单属性
SqlColumn包含sql列名称,如果是主键和列类型
[AttributeUsage(AttributeTargets.Property,Inherited=false)]
public class SqlColumn : Attribute
{
public SqlColumn(string columnName, Type valueType, bool primaryKey)
{
_ColumnName = columnName;
_ValueType = valueType;
_PrimaryKey = primaryKey;
}
private string _ColumnName;
private Type _ValueType;
private bool _PrimaryKey;
public string ColumnName
{
get
{
return this._ColumnName;
}
set
{
_ColumnName = value;
}
}
public Type ValueType
{
get
{
return this._ValueType;
}
set
{
_ValueType = value;
}
}
public bool PrimaryKey
{
get
{
return this._PrimaryKey;
}
set
{
_PrimaryKey = value;
}
}
}
只保存sql表名的
的SqlTable [AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=false)]
public class SqlTable : Attribute
{
public SqlTable(string TableName)
{
this._TableName = TableName;
}
protected String _TableName;
public String TableName
{
get
{
return this._TableName;
}
}
}
和一个sql命令生成器,用于在集合中创建相关的sql命令,更改事件处理程序和属性更改事件处理程序
public static class SqlGenerator
{
public static SqlCommand GenerateSelectCommand<T>()
{
string TableName = GetTableName<T>();
PropertyInfo[] props = GetPropertyInfos<T>();
//StringBuilder sbWhere = new StringBuilder(" WHERE ");
StringBuilder sbColumns = new StringBuilder(" ");
var cmd = new SqlCommand();
foreach (var prop in props)
{
sbColumns.Append(prop.Name);
}
cmd.CommandText =
"SELECT " +
sbColumns.ToString().TrimEnd(',') +
" FROM " + TableName;
return cmd;
}
public static SqlCommand GenerateInsertCommand<T>(object Obj)
{
string TableName = GetTableName<T>();
PropertyInfo[] props = GetPropertyInfos<T>();
var cmd = new SqlCommand();
StringBuilder sbColumns = new StringBuilder(" ");
StringBuilder sbValues = new StringBuilder(" ");
foreach(var prop in props)
{
var sqlColumnAttr = (SqlColumn)prop.GetCustomAttribute(typeof(SqlColumn), false);
var colValue = prop.GetValue(Obj);
if(!sqlColumnAttr.PrimaryKey && colValue!=null)
{
sbColumns.AppendFormat("{0},",sqlColumnAttr.ColumnName);
sbValues.AppendFormat("@{0},", sqlColumnAttr.ColumnName);
var param = new SqlParameter("@" + sqlColumnAttr.ColumnName, colValue);
param.DbType = (DbType)Enum.Parse(typeof(DbType), sqlColumnAttr.ValueType.Name);
cmd.Parameters.Add(param);
}
}
cmd.CommandText = "INSERT INTO " + TableName +"("+ sbColumns.ToString().TrimEnd(',') +") VALUES(" + sbValues.ToString().TrimEnd(',') + ");SELECT SCOPE_IDENTITY();";
return cmd;
}
public static SqlCommand GenerateUpdateCommand<T>(object Obj,IEnumerable<string> PropertyNamesThatChanged)
{
string TableName = GetTableName<T>();
PropertyInfo[] props = GetPropertyInfos<T>().Where(pinfo=>!PropertyNamesThatChanged.Contains(pinfo.Name)).ToArray();
var cmd = new SqlCommand();
StringBuilder sbValues = new StringBuilder(" ");
StringBuilder sbWhere = new StringBuilder(" WHERE ");
foreach (var prop in props)
{
var sqlColumnAttr = (SqlColumn)prop.GetCustomAttribute(typeof(SqlColumn), false);
var colValue = prop.GetValue(Obj);
if (!sqlColumnAttr.PrimaryKey && colValue != null)
{
sbValues.AppendFormat("{0}=@{0},", sqlColumnAttr.ColumnName);
var param = new SqlParameter("@" + sqlColumnAttr.ColumnName, colValue);
param.DbType = (DbType)Enum.Parse(typeof(DbType), sqlColumnAttr.ValueType.Name);
cmd.Parameters.Add(param);
}
else if(sqlColumnAttr.PrimaryKey)
{
sbWhere.AppendFormat("{0}=@{0}", sqlColumnAttr.ColumnName);
var param = new SqlParameter("@" + sqlColumnAttr.ColumnName, colValue);
param.DbType = (DbType)Enum.Parse(typeof(DbType), sqlColumnAttr.ValueType.Name);
cmd.Parameters.Add(param);
}
}
cmd.CommandText = "UPDATE " + TableName + sbValues.ToString().TrimEnd(',') + sbWhere.ToString();
return cmd;
}
public static SqlCommand GenerateDeleteCommand<T>(object Obj)
{
string TableName = GetTableName<T>();
PropertyInfo[] props = GetPropertyInfos<T>();
StringBuilder sbWhere = new StringBuilder(" WHERE ");
var cmd = new SqlCommand();
foreach (var prop in props)
{
var sqlColumnAttr = (SqlColumn)prop.GetCustomAttribute(typeof(SqlColumn), false);
if(sqlColumnAttr.PrimaryKey)
{
var colValue = prop.GetValue(Obj);
sbWhere.AppendFormat("{0}=@{0}", sqlColumnAttr.ColumnName);
var param = new SqlParameter("@" + sqlColumnAttr.ColumnName, colValue);
param.DbType = (DbType)Enum.Parse(typeof(DbType), sqlColumnAttr.ValueType.Name);
cmd.Parameters.Add(param);
}
}
cmd.CommandText = "DELETE FROM " + TableName + sbWhere.ToString();
return cmd;
}
public static string GetTableName<T>()
{
return typeof(T).GetAttributeValue((SqlTable sqlTable)=> sqlTable.TableName);
}
public static PropertyInfo[] GetPropertyInfos<T>()
{
return typeof(T).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(SqlColumn))).ToArray();
}
public static TValue GetAttributeValue<TAttribute, TValue>(
this Type type,
Func<TAttribute, TValue> valueSelector)
where TAttribute : Attribute
{
var att = type.GetCustomAttributes(
typeof(TAttribute), true
).FirstOrDefault() as TAttribute;
if (att != null)
{
return valueSelector(att);
}
return default(TValue);
}
}