📄 databaseloader.cs
字号:
using System;
using System.Collections.Generic;
using System.Text;
using Oracle.DataAccess.Client;
using System.Reflection;
using System.Data;
using OracleDALGen.Classes;
using OracleDALGen.Classes.Attributes;
using System.Collections;
using OracleDALGen.Classes.Database;
using System.Threading;
namespace OracleDALGen.Classes
{
public delegate void ObjectChangedDelegate(object sender, OracleNotificationEventArgs e);
public class DatabaseLoader : IDisposable
{
/*
* Connection for receiving Oracle notifications
*/
private static OracleConnection ntfConnection = null;
private static OracleDependency dep = null;
private const string inPrefix = "p";
private const string outPrefix = "x";
public event ObjectChangedDelegate ObjectChanged;
public DatabaseLoader()
{
}
#region Load methods
public T LoadSingle<T>(Param[] paramArray, OraConnection connection)
{
IList list = (IList)Load(typeof(T), null, paramArray, GetClassDatabaseType(typeof(T), Method.Select), connection);
if (list.Count > 0)
return (T)list[0];
else
return default(T);
}
public IList<T> LoadAll<T>(OraConnection connection)
{
return LoadAll<T>(new Param[0], connection);
}
public IList<T> LoadAll<T>(Param[] paramArray, OraConnection connection)
{
IList list = (IList)Load(typeof(T), null, paramArray, GetClassDatabaseType(typeof(T), Method.Select), connection);
IList<T> ret = new List<T>();
foreach (object o in list)
ret.Add((T)o);
return ret;
}
protected object LoadSingle(Type type, Param[] paramArray, ClassDatabaseType cmd, OraConnection connection)
{
IList list = (IList)Load(type, null, paramArray, cmd, connection);
if (list.Count > 0)
return list[0];
else
return null;
}
protected object LoadAll(Type type, Type collectionType, Param[] paramArray, ClassDatabaseType cmd, OraConnection connection)
{
return Load(type, collectionType, paramArray, cmd, connection);
}
protected object Load(Type type, Type collectionType, Param[] paramArray, ClassDatabaseType cmd, OraConnection connection)
{
DateTime startTime = DateTime.Now;
List<OracleParameter> op = new List<OracleParameter>();
/*
* Adding data output parameter
*/
if (cmd.Type == CommandType.StoredProcedure)
op.Add(new OracleParameter("cur", OracleDbType.RefCursor, ParameterDirection.ReturnValue));
/*
* Adding id parameter(s)
*/
IList<IdColumn> idList = GetCustomAttributes<IdColumn>(type);
foreach (IdColumn idCol in idList)
{
object value = null;
if (paramArray != null)
{
foreach (Param p in paramArray)
{
if (p.ColumnName.Equals(idCol.ColumnName))
value = p.Value;
}
}
op.Add(CreateParameter(value, idCol.ColumnName, ParameterDirection.Input));
}
/*
* Loading data from the database
*/
DataSet ds = DBUtils.LoadDataset(cmd.Text, op, cmd.Type, connection);
IList list = null;
if (collectionType == null) // Create a standard List of object collection if nothing else is specified
list = new List<object>();
else
/*
* Create a specified collection.
* Since all collections implements the IList interface, cast to IList and treat it as such.
* Eg. List<TestObject> will be treated as IList. But since this only occures internally it does not matter.
*/
list = (IList)Activator.CreateInstance(collectionType);
if (ds != null)
{
DataTable dt = ds.Tables["data"];
foreach (DataRow row in dt.Rows)
{
/*
* Creating new object
*/
object bo = Activator.CreateInstance(type);
/*
* Setting attribute values
*/
SetAttributeValues(type, row, bo, connection);
list.Add(bo);
}
}
TimeSpan ts = DateTime.Now - startTime;
Console.WriteLine("Loaded in: " + ts.TotalMilliseconds);
return list;
}
private void SetAttributeValues(Type type, DataRow row, object bo, OraConnection connection)
{
Dictionary<PropertyInfo, object> objectColumns = new Dictionary<PropertyInfo, object>();
Dictionary<PropertyInfo, object> listColumns = new Dictionary<PropertyInfo, object>();
PropertyInfo[] propsInfo = type.GetProperties();
foreach (PropertyInfo pi in propsInfo)
{
DbColumn attr = GetCustomAttribute<DbColumn>(pi);
if (attr != null && !(attr is ListColumn))
{
if (row.Table.Columns.IndexOf(attr.ColumnName) == -1)
throw new Exception(string.Format("Column {0} does not exist for class {1}", attr.ColumnName, bo.GetType().Name));
object objectValue = row[attr.ColumnName];
if (attr is ObjectColumn && !(attr is ForeignKeyColumn)) // If the column is a foreign key load object instead
objectColumns.Add(pi, objectValue);
else
{ // If this is an ordinary column, set value
if (objectValue is DBNull)
objectValue = null;
pi.SetValue(bo, objectValue, null);
}
}
else
listColumns.Add(pi, null);
}
/*
* Loading foreign key objects
*/
LoadForeignKeyObjects(bo, objectColumns, connection);
/*
* Loading a list of objects
*/
LoadListObjects(bo, listColumns, connection);
}
private void LoadListObjects(object bo, Dictionary<PropertyInfo, object> listColumns, OraConnection connection)
{
Dictionary<PropertyInfo, object>.Enumerator enuList = listColumns.GetEnumerator();
while (enuList.MoveNext())
{
ListColumn attr = GetCustomAttribute<ListColumn>(enuList.Current.Key);
DatabaseLoader dl = new DatabaseLoader();
/*
* Extracting parameters
*/
List<Param> loadParam = new List<Param>();
foreach (string str in attr.ColumnName.Split(','))
loadParam.Add(new Param(str, GetColumnValue(bo, str)));
//object loadParam = GetColumnValue(bo, attr.ColumnName);
/*
* Fetching the generic collection type
*/
object o = enuList.Current.Key.GetValue(bo, null);
Type listType = o.GetType();
/*
* Loading objects, and asking for a result with the specified generic collection type
*/
o = dl.LoadAll(attr.ChildType, listType, loadParam.ToArray(), attr.Command, connection);
enuList.Current.Key.SetValue(bo, o, null);
}
}
private void LoadForeignKeyObjects(object bo, Dictionary<PropertyInfo, object> objectColumns, OraConnection connection)
{
Dictionary<PropertyInfo, object>.Enumerator enuForeign = objectColumns.GetEnumerator();
while (enuForeign.MoveNext())
{
ObjectColumn attr = GetCustomAttribute<ObjectColumn>(enuForeign.Current.Key);
/*
* Executing LoadSingle for each ObjectColumn attribute found
*/
if (!(enuForeign.Current.Value is DBNull))
{
DatabaseLoader dl = new DatabaseLoader();
object o = dl.LoadSingle(attr.ChildType, new Param[] { new Param(attr.ColumnName, enuForeign.Current.Value) }, GetClassDatabaseType(attr.ChildType, Method.Select), connection);
enuForeign.Current.Key.SetValue(bo, o, null);
}
}
}
#endregion
#region Save methods
public virtual T Save<T>(T dataObject, OraConnection connection)
{
return (T)Save(typeof(T), dataObject, null, GetClassDatabaseType(typeof(T), Method.Merge), connection);
}
protected virtual object Save(Type type, object dataObject, Param[] paramArray, ClassDatabaseType cmd, OraConnection connection)
{
DateTime startTime = DateTime.Now;
List<OracleParameter> op = new List<OracleParameter>();
/*
* Adding data input parameter(s)
*/
PropertyInfo[] propsInfo = dataObject.GetType().GetProperties();
int idxInput = 0;
foreach (PropertyInfo pi in propsInfo)
{
DbColumn bt = GetCustomAttribute<DbColumn>(pi);
if (bt != null)
{
object objectValue = null;
if (paramArray != null && bt.ColumnName == paramArray[0].ColumnName )
objectValue = paramArray[0].Value;
else
objectValue = pi.GetValue(dataObject, null);
if (bt is ObjectColumn && !(bt is ListColumn) && !(bt is ForeignKeyColumn))
{
/*
* Saving child object
*/
ObjectColumn oc = (ObjectColumn)bt;
objectValue = Save(oc.ChildType, objectValue, null, GetClassDatabaseType(oc.ChildType, Method.Merge), connection);
/*
* Fetching id column values
*/
PropertyInfo[] childProps = oc.ChildType.GetProperties();
foreach (PropertyInfo childPi in childProps)
{
IdColumn idCol = GetCustomAttribute<IdColumn>(childPi);
if (idCol != null)
{
object colValue = GetColumnValue(objectValue, idCol.ColumnName);
op.Add(CreateParameter(colValue, bt.ColumnName, ParameterDirection.Input));
}
}
}
else if (!(bt is ListColumn)) // Adding oracle parameter
op.Add(CreateParameter(objectValue, bt.ColumnName, ParameterDirection.Input));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -