实体类:
[Serializable]
public class ProductInfo
{
string Code;
string Name;
}
... 有很多类似的实体类.数据访问类:
public class ProductDa
{
public List<ProductInfo> GetModels()
{
List<ProductInfo> list = new List<ProductInfo>();
using (SqlDataReader rdr = SqlHelper.ExecuteReader(this.connectionString ,CommandType.StoredProcedure,SELECT,null))
{
while (rdr.Read())
{
ProductInfo tmp = new ProductInfo(
rdr.GetString(0),
rdr.GetString(1),
list.Add(tmp);
line++;
}
}
return list ;
}
}现在问题是,针对每一个实体类的数据访问类都要写这样重复的代码,(只是实体类不同,实体构造函数参数不同).有没有可能用泛型解决这样的问题,如上只要一个
List<T> GetModels() , 然后传入不同的实体类型即可.如可则在实际应用中可省很多代码.请做过的朋友给点思路,请对此感兴趣的朋友帮忙顶顶,谢谢!
[Serializable]
public class ProductInfo
{
string Code;
string Name;
}
... 有很多类似的实体类.数据访问类:
public class ProductDa
{
public List<ProductInfo> GetModels()
{
List<ProductInfo> list = new List<ProductInfo>();
using (SqlDataReader rdr = SqlHelper.ExecuteReader(this.connectionString ,CommandType.StoredProcedure,SELECT,null))
{
while (rdr.Read())
{
ProductInfo tmp = new ProductInfo(
rdr.GetString(0),
rdr.GetString(1),
list.Add(tmp);
line++;
}
}
return list ;
}
}现在问题是,针对每一个实体类的数据访问类都要写这样重复的代码,(只是实体类不同,实体构造函数参数不同).有没有可能用泛型解决这样的问题,如上只要一个
List<T> GetModels() , 然后传入不同的实体类型即可.如可则在实际应用中可省很多代码.请做过的朋友给点思路,请对此感兴趣的朋友帮忙顶顶,谢谢!
解决方案 »
- 关于ListBox里单击改变所选条目的事件,求指点
- 急!根据不同类型 获取相同方法名的不同参数值
- HttpWebRequest获取网页源码后如何模拟执行代码?
- 这样的功能怎么实现?__________________--------->
- 请问一个ArrayList类型转换的问题~
- [新手求助]C# winfrom 控件listview 如何显示每行一条
- C#连接SQL2000 问题
- [★★★只有10分了....] 读取 文件 的方法 ??
- 关于TreeView的问题,紧急,高手帮忙
- 高手帮忙!!!! 打开网页乱码问题!!!!!!!!!!!!!100分
- c#.net多重添加数据库的问题,DataGrid
- 请问如何实现在一个win form启动时自动按下一个按钮?
然后其它的数据访问类继承基类....并传入实体类给泛型参数...
[Serializable]
public class ProductInfo
{
public string Code;
public string Name;
}public ArrayList GetModels(Type AType)
{
if (AType == null) return null;
object vObject = Activator.CreateInstance(AType);
ArrayList Result = new ArrayList();
Result.Add(vObject);
int i = 0;
foreach (FieldInfo vFieldInfo in AType.GetFields())
{
vFieldInfo.SetValue(vObject, "Zswang 路过" + i);
i++;
}
return Result;
}private void button1_Click(object sender, EventArgs e)
{
ArrayList vArrayList = GetModels(typeof(ProductInfo));
Text = ((ProductInfo)vArrayList[0]).Name;
}
{
vFieldInfo.SetValue(vObject, "Zswang 路过" + i);
i++;
}这段循环怎么保证字段和变量能一一对应阿?
>这段循环怎么保证字段和变量能一一对应阿?这个对应是声明类型时做的事情michael_zy提供的方案也不错,通过继承同一类型实现
在重载方法设计中可以考虑处理和数据库字段对应的关系
foreach (FieldInfo vFieldInfo in AType.GetFields())
{
vFieldInfo.SetValue(vObject, "Zswang 路过" + i);
i++;
}这段循环怎么保证字段和变量能一一对应阿?
============================================
可以这样改一下
using (SqlDataReader rdr = SqlHelper.ExecuteReader(this.connectionString ,CommandType.StoredProcedure,SELECT,null))
vFieldInfo.SetValue(vObject, rdr[vFieldInfo.Name]);命名类的实例名时保证跟数据库字段名一致就OK了。
因为楼主的实体类之间并不一定有关系,让他们派生自共同的主先,只能保证一定程序上的强类型。我的意见是结合michael_zy和zswang的意见做
{
public class EntityInputControl<T> : EntityControlBase<T>
{ private T _PageEntity; /// <summary>
/// 数据保存,可以重写该方法
/// </summary>
/// <returns></returns>
public virtual bool SaveData()
{
bool flag = false;
T objType = this.PageEntity;
//调用WebService保存数据对象
return flag;
} /// <summary>
/// 获取用户控件业务实体的数据对象
/// </summary>
public virtual T PageEntity
{
get
{
if (_PageEntity != null)
return this._PageEntity;
ArrayList ctlList = new ArrayList();
//遍历用户控件的数据子控件
foreach (System.Web.UI.Control ctl in this.Controls)
{
if ( this.IsEntityProperty( ctl ) )
{
ctlList.Add(ctl);
}
}
//数据实体属性集合
PropertyInfo[] infoArr = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
object objData = Activator.CreateInstance(typeof(T));
//遍历数据实体对象,并设置数据实体的属性值
for (int num = 0; num < infoArr.Length; num++)
{
foreach (object item in ctlList)
{
IWControl iwc = (IWControl)item;
if (iwc.ColumnName.Equals(infoArr[num].Name))
{
infoArr[num].SetValue(objData, iwc.GetValue(), null);
ctlList.Remove(item);
break;
}
}
}
ctlList = null;
_PageEntity = (T)objData;
return _PageEntity;
}
} }
}
{
try
{
MetaData md = MetaDataManager.GetMetaData(typeof(T));
QueryCommandBuilder qcBuilder = new OleDb.OleDbQueryCommandBuilder();
qcBuilder.EntityType = md.EntityType;
qcBuilder.PersistType = EntityPersistType.Query;
qcBuilder.Filter = filter;
QueryCommand cmd = qcBuilder.GetQueryCommand();
DbDataReader reader = DAO.ExecuteDataReader(cmd.CommandText, cmd.Parameters);
return DbDataReaderToList<T>(reader);
}
catch
{
return null;
} }#region private Method
private object DbDataReaderToList<T>(DbDataReader reader)
{
List<T> list = new List<T>();
MetaData md = MetaDataManager.GetMetaData(typeof(T));
while (reader.Read())
{
T obj = Activator.CreateInstance<T>();
foreach (PropertyInfo info in obj.GetType().GetProperties())
{
if (!reader.IsDBNull(reader.GetOrdinal(md.FieldMeteDatas[info.Name].ColumnName)))
{
info.SetValue(obj, reader[md.FieldMeteDatas[info.Name].ColumnName], null);
}
}
list.Add(obj);
}
return list;
}
#endregion
自己程序的两个方法代码,以供参考
直接定义一大堆属性,令属性与数据库字段重名,便可通过反射来创建实体类……
如果嫌效率差,可以尝试挑刺、NInputer还有俺共同努力的结果,超强ORM转换器。
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection.Emit;
using System.Reflection;namespace Ivony.Data.ObjectData
{
/// <summary>
/// ORM相关操作的帮助器
/// </summary>
public static class ORMHelper
{ /// <summary>
/// 构建一个ORM转换器
/// </summary>
/// <typeparam name="T">转换的目标类型</typeparam>
/// <param name="schema">数据架构</param>
/// <res>
/// 感谢:tiaoci、Ninputer。
/// </res>
/// <returns>转换器</returns>
public static ORMDataRowConverter<T> BuildConverter<T>( DataTable schema )
{
DynamicMethod method = new DynamicMethod(
"DataRowToEntity_" + schema.GetHashCode().ToString(), null,
new Type[] { typeof( DataRow ), typeof( T ) },
typeof( T ) ); MethodInfo DataRow_Item_get = typeof( DataRow ).GetMethod( "get_Item", new Type[] { typeof( int ) } );
ILGenerator il = method.GetILGenerator();
foreach ( FieldInfo field in typeof( T ).GetFields( BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public ) )
{
string fieldName = field.Name.TrimStart( '_' );
if ( schema.Columns.Contains( fieldName ) )
{
il.Emit( OpCodes.Ldarg_1 );
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Ldc_I4, schema.Columns[fieldName].Ordinal );
EmitCall( il, DataRow_Item_get );
EmitCastObj( il, field.FieldType );
il.Emit( OpCodes.Stfld, field );
}
} il.Emit( OpCodes.Ret ); return (ORMDataRowConverter<T>) method.CreateDelegate( typeof( ORMDataRowConverter<T> ) );
} /// <summary>
/// 构建一个ORM转换器
/// </summary>
/// <typeparam name="T">转换的目标类型</typeparam>
/// <res>
/// 感谢:tiaoci、Ninputer。
/// </res>
/// <returns>转换器</returns>
public static ORMDataRowConverter<T> BuildConverter<T>()
{ /*
.method public hidebysig static void ConvertEntity(class [System.Data]System.Data.DataRow data,
class Ivony.Data.ObjectData.Entity entity) cil managed
{
// 代码大小 79 (0x4f)
.maxstack 3
.locals init (class [System.Data]System.Data.DataColumnCollection V_0,
class [System.Data]System.Data.DataColumn V_1)
IL_0000: ldarg.0
IL_0001: callvirt instance class [System.Data]System.Data.DataTable [System.Data]System.Data.DataRow::get_Table()
IL_0006: callvirt instance class [System.Data]System.Data.DataColumnCollection [System.Data]System.Data.DataTable::get_Columns()
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: ldstr "a"
IL_0012: callvirt instance class [System.Data]System.Data.DataColumn [System.Data]System.Data.DataColumnCollection::get_Item(string)
IL_0017: dup
IL_0018: stloc.1
IL_0019: brfalse.s IL_002d
IL_001b: ldarg.1
IL_001c: ldarg.0
IL_001d: ldloc.1
IL_001e: callvirt instance object [System.Data]System.Data.DataRow::get_Item(class [System.Data]System.Data.DataColumn)
IL_0023: unbox.any [mscorlib]System.Int32
IL_0028: stfld int32 Ivony.Data.ObjectData.Entity::a
IL_002d: ldloc.0
IL_002e: ldstr "b"
IL_0033: callvirt instance class [System.Data]System.Data.DataColumn [System.Data]System.Data.DataColumnCollection::get_Item(string)
IL_0038: dup
IL_0039: stloc.1
IL_003a: brfalse.s IL_004e
IL_003c: ldarg.1
IL_003d: ldarg.0
IL_003e: ldloc.1
IL_003f: callvirt instance object [System.Data]System.Data.DataRow::get_Item(class [System.Data]System.Data.DataColumn)
IL_0044: unbox.any [mscorlib]System.Int32
IL_0049: stfld int32 Ivony.Data.ObjectData.Entity::b
IL_004e: ret
} // end of method ORMHelper::ConvertEntity */
DynamicMethod method = new DynamicMethod( "DataRowToEntity", null, new Type[] { typeof( DataRow ), typeof( T ) }, typeof( T ) );
ILGenerator il = method.GetILGenerator(); il.DeclareLocal( typeof( DataColumnCollection ) );
il.DeclareLocal( typeof( DataColumn ) ); il.Emit( OpCodes.Ldarg_0 );
EmitCall( il, typeof( DataRow ).GetProperty( "Table" ).GetGetMethod() );
EmitCall( il, typeof( DataTable ).GetProperty( "Columns" ).GetGetMethod() );
il.Emit( OpCodes.Stloc_0 ); foreach ( FieldInfo field in typeof( T ).GetFields( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ) )
{
Label label = il.DefineLabel();
string fieldName = field.Name.TrimStart( '_' ); il.Emit( OpCodes.Ldloc_0 );
il.Emit( OpCodes.Ldstr, fieldName );
EmitCall( il, typeof( DataColumnCollection ).GetProperty( "Item", new Type[] { typeof( string ) } ).GetGetMethod() ); il.Emit( OpCodes.Dup );
il.Emit( OpCodes.Stloc_1 ); il.Emit( OpCodes.Brfalse, label ); il.Emit( OpCodes.Ldarg_1 );
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Ldloc_1 ); EmitCall( il, typeof( DataRow ).GetProperty( "Item", new Type[] { typeof( DataColumn ) } ).GetGetMethod() );
EmitCastObj( il, field.FieldType ); il.Emit( OpCodes.Stfld, field ); il.MarkLabel( label );
} il.Emit( OpCodes.Ret ); return (ORMDataRowConverter<T>) method.CreateDelegate( typeof( ORMDataRowConverter<T> ) );
}
private static void EmitCastObj( ILGenerator il, Type targetType )
{
if ( targetType.IsValueType )
il.Emit( OpCodes.Unbox_Any, targetType );
else
il.Emit( OpCodes.Castclass, targetType );
}
private static void EmitCall( ILGenerator il, MethodInfo method )
{
if ( method.IsVirtual )
il.Emit( OpCodes.Callvirt, method );
else
il.Emit( OpCodes.Call, method );
}
} /// <summary>
/// 代表从DataRow中获取数据的ORM转换方法
/// </summary>
/// <typeparam name="T">转换的目标类型</typeparam>
/// <param name="data">数据来源</param>
/// <param name="entity">被写入的包含数据的实例对象</param>
public delegate void ORMDataRowConverter<T>( DataRow data, T entity );
}
一般人我不告诉她……
别这么小气嘛,我也做了一个ORM方面的东西,速度还不赖,现在的主要问题就是分页不好处理,不知你有什么良策。
强类型分页器,ObjectDataPagination和ObjectDataCollection
数据分页器,IDataPagination /// <summary>
/// 强类型数据分页器
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
public class ObjectDataPagination<T> : IObjectDataPagination<T>, IPaginationBase
{ private IObjectDataConverter<T> _converter;
private ObjectDataConvertMethod<T> _converterMethod;
private IDataPagination _dataSource; public ObjectDataPagination( IObjectDataConverter<T> converter, IDataPagination dataSource )
{
if ( converter == null )
throw new ArgumentNullException( "converter" );
if ( dataSource == null )
throw new ArgumentNullException( "dataSource" ); _converter = converter;
_dataSource = dataSource;
} public ObjectDataPagination( ObjectDataConvertMethod<T> converter, IDataPagination dataSource )
{
if ( converter == null )
throw new ArgumentNullException( "converter" );
if ( dataSource == null )
throw new ArgumentNullException( "dataSource" ); _converterMethod = converter;
_dataSource = dataSource;
} public int GetCount()
{
return _dataSource.GetCount();
} public IList<T> GetPage( int pageindex )
{
System.Data.DataTable data = _dataSource.GetPage( pageindex ); if ( _converter != null )
return new ObjectDataCollection<T>( _converter, data );
else
return new ObjectDataCollection<T>( _converterMethod, data );
} public int PageSize
{
get { return _dataSource.PageSize; }
}
public IDataPagination DataPagination
{
get { return _dataSource; }
}
System.Collections.IEnumerable IPaginationBase.GetPage( int pageindex )
{
return GetPage( pageindex );
}
}
public class Class1<T>
{ public List<T> GetModels()
{
List<T> ms = new List<T>();
T obj; for (int i = 0; i < 5; i++)
{
obj = (T)Activator.CreateInstance(typeof(T));
foreach (PropertyInfo fi in typeof(T).GetProperties())
{
if (fi.Name == "Code")
fi.SetValue(obj, i.ToString(), null);
}
ms.Add(obj);
}
return ms;
}
}测试: static void Main(string[] args)
{
Class1<CompanyModel> cm = new Class1<CompanyModel>();
List<CompanyModel> lcm = cm.GetModels(); foreach (CompanyModel m in lcm)
{
Console.WriteLine(m.Code );
}
Console.ReadKey();
}
有没有考虑过直接用DataReader?