ASP。NET开发中, 业务实体需要通过数据访问层与数据库交互,因此,你必须为每个业务实体类编写相对应的数据访问层代码。以下代码解决了这个问题: 所有的业务实体只要派生自一个指定的类(这里是SwContent类),那么只须定义他与数据库相对应的字段属性,它所继承的Select(),Insert(),UpDate(),Delete()方法(无须重写)便可以完成(1),从数据库中获取指定数据填充实体类;(2),从指定实体对象获取数据插入到数据库中;(3),从指定实体对象获取数据更新数据库中对应的数据项;(4),删除数据。下面的主要代码是通过属性实现的。其思路是:实体类提供一个共公方法(在他们的基类中实现)可以返回IDataParameter的数组类型。parameterName标记属性名,Value是属性值。数据访问层代码对该数组进行矢代,构造Sql语句后执行操作。
注意: 业务实体类的公共属性名必须与数据库的相关字段名保持一至,且数据库中的主键要保持一直(这里是Id)。
为了兼容多层开发模式,我定义了一个 ISwDataProperty接口。SwContent类及他的派生类将实现该接口。
public interface ISwDataProperty
{
int Id
{
get; //与数据库的主键对应,且所有表的主键都要相同。
}
string Table
{
get; //与实体类相对应的数据库表名
}
object this[int index] //存取访问器,主要使用属性实现,代码在后面贴出
{
get;
set;
}
void AcceptChanges(); //只用于UpDate时;与DataSet的AcceptChanges()方法作用类似,若不调用,则表示更新数据库中的所有项;调用他,则只更新在调用后所设置的数据项。
IDataParameter[] GetSwDataParameters(); //返回与实体类相关的参数列表。
}
/////////////////////////////////////////////////////////////////////////////
因此我还定义了SwDataParameter类(我们只需要使用ParameterName,Value两个属性。):
public class SwDataParameter:IDataParameter
{
private object _value;
private string _parameterName;
#region IDataParameter 成员
public DbType DbType
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public ParameterDirection Direction
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public bool IsNullable
{
get { throw new Exception("The method or operation is not implemented."); }
}
public string ParameterName
{
get
{
return _parameterName;
}
set
{
_parameterName = value;
}
}
public string SourceColumn
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public DataRowVersion SourceVersion
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public object Value
{
get
{
return _value;
}
set
{
_value = value;
}
}
#endregion
}
/////////////////////////////////////////////////////////////////////////////
在贴出业务实体基类的ISwDataProperty实现方式之前,我们定义一个属性类,他只用来做标记(做此标记的属性将不会用来进行与数据库相关连的操作)。
[AttributeUsage(AttributeTargets.Property)]
public class SwNotDataParameterAttribute : Attribute
{
/// <summary>
/// 只用做标记,指示该属性不是数据库字段
/// </summary>
public SwNotDataParameterAttribute()
{
}
}
/////////////////////////////////////////////////////////////////
在ISwDataProperty中定义的3个属性都要加上[SwNotDataParameter()]标记:
public abstract class SwContent:ISwDataProperty
{
protected int _id;
protected string _table;
protected object _upDateRef = null;
public SwContent()
{
}
#region ISwDataProperty 成员
[SwNotDataParameter()]
public int Id
{
get
{
return _id;
}
set
{
_id = value;
}
}
[SwNotDataParameter()]
public string Table
{
get
{
return _table;
}
}
[SwNotDataParameter()]
public object this[int index]
{
get
{
int i = 0;
object obj=null;
foreach (PropertyInfo item in this.GetType().GetProperties())
{
if (item.GetCustomAttributes(typeof(SwNotDataParameterAttribute), true).Length < 1)
{
if (i == index)
{
if (item.GetGetMethod().ReturnType == typeof(BoolEnum)) //BoolEnum是我自定义的枚举。
{
return Convert.ToInt32(item.GetValue(this, null));
}
obj = item.GetValue(this, null);
if (item.GetGetMethod().ReturnType == typeof(string) &&
string.IsNullOrEmpty((string)obj))
{
return string.Empty;
}
break;
}
i++;
}
}
return obj;
}
set
{
int i = 0;
foreach (PropertyInfo item in this.GetType().GetProperties())
{
if (item.GetCustomAttributes(typeof(SwNotDataParameterAttribute), true).Length < 1)
{
if (i == index)
{
if (item.GetGetMethod().ReturnType == typeof(BoolEnum))
{
item.SetValue(this, (BoolEnum)value, null);
break;
}
item.SetValue(this, value, null);
break;
}
i++;
}
}
}
}
public void AcceptChanges()
{
_upDateRef = this.MemberwiseClone();
}
public IDataParameter[] GetSwDataParameters()
{
PropertyInfo[] swProInfo = this.GetType().GetProperties();
int i = 0;
int j = 0;
IDataParameter[] _swDataParameters = new SwDataParameter[swProInfo.Length];
foreach (PropertyInfo item in swProInfo)
{
if (item.GetCustomAttributes(typeof(SwNotDataParameterAttribute),true).Length < 1)
{
if (_upDateRef == null || ((ISwDataProperty)_upDateRef)[j].ToString() != this[j].ToString())
{
_swDataParameters[i] = new SwDataParameter();
_swDataParameters[i].ParameterName = item.Name;
_swDataParameters[i].Value = this[j];
i++;
}
j++;
}
}
Array.Resize<IDataParameter>(ref _swDataParameters, i);
return _swDataParameters;
}
#endregion
public void Select()
{
_upDateRef = null;
SwContentOperate.Select(this);
}
public virtual bool Insert()
{
_upDateRef = null;
return SwContentOperate.Insert(this);
}
public bool UpDate()
{
return SwContentOperate.UpDate(this);
}
public bool Delete()
{
return SwContentOperate.Delete(this.Id, this.Table);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
这里是数据访问类:
public class SwContentOperate
{
public static void Select(ISwDataProperty obj)
{
try
{
SqlConnection newConnect = SwConnect.Create();
string sql = "select * from "+obj.Table+" where Id="+obj.Id;
SqlDataAdapter swDataAdapter = new SqlDataAdapter(sql, newConnect);
newConnect.Open();
DataSet swDS = new DataSet();
swDataAdapter.Fill(swDS, obj.Table);
newConnect.Close();
DataRow swDataRow = swDS.Tables[0].Rows[0];
if (swDS.Tables[0].Rows.Count <1)
{
obj = null;
swDS.Clear();
return;
}
IDataParameter[] swPC = obj.GetSwDataParameters();
int i = 0;
object objVal = null;
foreach (IDataParameter item in swPC)
{
try
{
objVal = swDataRow[item.ParameterName];
}
catch
{
objVal = null;
}
obj[i] = objVal;
i++;
}
swDS.Clear();
}
catch(Exception e)
{
throw new SwLogException("ERROR", e);
}
}
public static bool Insert(ISwDataProperty obj)
{
try
{
SqlConnection newConnect = SwConnect.Create();
string sql = "insert into "+obj.Table+" (";
string sqlLast = ")values(";
SqlCommand swCommand = new SqlCommand();
SqlParameter swParameter;
IDataParameter[] swPC = obj.GetSwDataParameters();
int i = 0;
foreach (IDataParameter item in swPC)
{
if (i != swPC.Length - 1)
{
sql += item.ParameterName + ",";
sqlLast += "@" + item.ParameterName + ",";
}
else
{
sql += item.ParameterName;
sqlLast += "@" + item.ParameterName + ")";
}
swParameter = new SqlParameter();
swParameter.ParameterName = "@"+item.ParameterName;
swParameter.Value = item.Value;
swCommand.Parameters.Add(swParameter);
i++;
}
swCommand.CommandText = sql + sqlLast;
swCommand.Connection = newConnect;
newConnect.Open();
swCommand.ExecuteNonQuery();
newConnect.Close();
}
catch(Exception e)
{
throw new SwLogException("ERROR", e);
}
return true;
}
public static bool UpDate(ISwDataProperty obj)
{
try
{
SqlConnection newConnect = SwConnect.Create();
string sql = "update "+obj.Table+" set ";
SqlCommand swCommand = new SqlCommand();
SqlParameter swParameter;
IDataParameter[] swPC = obj.GetSwDataParameters();
if (swPC.Length < 1)
{
newConnect.Close();
return true;
}
int i = 0;
swCommand.Parameters.Add(new SqlParameter("@Table",obj.Table));
foreach (IDataParameter item in swPC)
{
if (i != swPC.Length - 1)
{
sql += item.ParameterName + "=@" + item.ParameterName + ",";
}
else
{
sql += item.ParameterName + "=@" + item.ParameterName+" where Id="+obj.Id;
}
swParameter = new SqlParameter();
swParameter.ParameterName = "@"+item.ParameterName;
swParameter.Value = item.Value;
swCommand.Parameters.Add(swParameter);
i++;
}
swCommand.CommandText = sql;
swCommand.Connection = newConnect;
newConnect.Open();
swCommand.ExecuteNonQuery();
newConnect.Close();
}
catch
{
return false;
}
return true;
}
public static bool Delete(int id,string table)
{
try
{
SqlConnection newConnect = SwConnect.Create();
string sql = "delete from "+table+" where id=" + id;
SqlCommand swCommand = new SqlCommand(sql, newConnect);
newConnect.Open();
swCommand.ExecuteNonQuery();
newConnect.Close();
}
catch
{
return false;
}
return true;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
实体类只要继承SwContent类既可。
public class NewClass:SwContent,ISwDataProperty
{
private int _parentId;
private string _name;
private string _text;
public SwContentOperate()
{
_table = "DatabaseTable"; //在构造函数中硬编码对应的表名。
}
public int ParentId
{
get
{
return _parentId;
}
set
{
_parentId = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
....................
//////////////////////
页面测试:
NewClass obj=new NewClass();
obj.Id=1;
obj.Select(); //获取数据库数据。
obj.Text="Test";
obj.UpDate(); //更新数据。
obj.Text="Test1";
obj.AcceptChanges(); //前面的设置obj.Text="Test1"将不会被更新到数据库。
obj.UpDate();
这是从几个装配件中整理出来的,所以代码比较混乱,如有错误,请海涵。