汎用データ・アクセス・レイヤ・フレームワーク

43672 ワード

1.フレーム
エンティティ・クラス、データ・アクセス・クラスのベース・クラス、およびユーザーORMappingのAttributeを定義します.
TableMappingAttribute:
using System;

namespace Core
{
[AttributeUsage(AttributeTargets.Class)]
public class TableMappingAttribute : Attribute
{
public String TableName {get;set;}
}
}

FieldMappingAttribute:
using System;

namespace Core
{
[AttributeUsage(AttributeTargets.Property)]
public class FieldMappingAttribute : Attribute
{
public String FieldName {get;set;}

public Boolean IsPrimary {get;set;}

public Boolean IsAutoIncrement {get;set;}
}
}

EntityBase:
using System;

namespace Core
{
public class EntityBase
{
Boolean isNew = true;
public Boolean IsNew
{
get { return isNew; }
set
{
isNew = value;
if (isNew == true)
{
isLoad = false;
isDeleted = false;
isDirty = false;
}
}
}

Boolean isDirty = false;
public Boolean IsDirty
{
get { return isDirty; }
set
{
if (isLoad)
{
isDirty = value;
}
}
}

Boolean isLoad = false;
public Boolean IsLoad
{
get { return isLoad; }
set
{
isLoad = value;
if (isLoad == true)
{
isNew = false;
isDeleted = false;
isDirty = false;
}
}
}

Boolean isDeleted = false;
public Boolean IsDeleted
{
get { return isDeleted; }
set
{
isDeleted = value;
if (isDeleted == true)
{
isNew = false;
isLoad = false;
isDirty = false;
}
}
}
}
}

ServiceBase:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;

namespace Core
{
public class ServiceBase<T> where T : EntityBase
{
#region
protected SqlConnection m_DalConnection = null;
protected SqlCommand m_DalCommand = null;
protected Dictionary<String, SqlParameter> m_DalCachedParameters = null;
#endregion

#region
private String m_TableName = string.Empty;
private String m_SelectSql = string.Empty;
private String m_InsertSql = string.Empty;
private String m_UpdateSql = string.Empty;
private PropertyInfo m_PrimaryFieldPropertyInfo = null;
private PropertyInfo m_AutoIncrementFieldPropertyInfo = null;
private Dictionary<String, PropertyInfo> m_CachedFieldPropertyInfo = null;
private DataTable m_TemplateDataTable = null;
#endregion

#region
protected ServiceBase(SqlConnection sqlConnection)
{
m_DalConnection = sqlConnection;
m_DalCommand = new SqlCommand();
m_DalCommand.CommandTimeout = 150;
m_DalCommand.Connection = m_DalConnection;

m_DalCachedParameters = new Dictionary<String, SqlParameter>();
m_CachedFieldPropertyInfo = new Dictionary<String, PropertyInfo>();

InitTableFieldMaping();
}

private void InitTableFieldMaping()
{
var tableMappingAttributes = typeof(T).GetCustomAttributes(typeof(TableMappingAttribute), false) as TableMappingAttribute[];
if (tableMappingAttributes.Length == 0)
{
throw new ApplicationException("Miss TableMappingAttribute defination");
}
m_TableName = tableMappingAttributes[0].TableName;

String updateSetSql = string.Empty;
String updateWhereSql = string.Empty;
String insertFieldsSql = string.Empty;
String insertValuesSql = string.Empty;
foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
{
var fieldMappingAttributes = propertyInfo.GetCustomAttributes(typeof(FieldMappingAttribute), false) as FieldMappingAttribute[];
if (fieldMappingAttributes.Length > 0)
{
String fieldName = fieldMappingAttributes[0].FieldName;
m_CachedFieldPropertyInfo.Add(fieldName, propertyInfo);

bool isPrimaryField = fieldMappingAttributes[0].IsPrimary;
bool isAutoIncrementField = fieldMappingAttributes[0].IsAutoIncrement;

if (isPrimaryField)
{
if (m_PrimaryFieldPropertyInfo != null)
{
throw new ApplicationException("Muiltiple Primary Field defination");
}
m_PrimaryFieldPropertyInfo = propertyInfo;
}

if (isAutoIncrementField)
{
if (m_AutoIncrementFieldPropertyInfo != null)
{
throw new ApplicationException("Muiltiple Auto Increment Field defination");
}
m_AutoIncrementFieldPropertyInfo = propertyInfo;
}

//SELECT SQL
if (m_SelectSql == string.Empty)
{
m_SelectSql = "[" + fieldName + "]";
}
else
{
m_SelectSql += ",[" + fieldName + "]";
}

//INSERT SQL
if (!isAutoIncrementField)
{
if (insertFieldsSql == string.Empty)
{
insertFieldsSql += "[" + fieldName + "]";
insertValuesSql += "@" + fieldName;
}
else
{
insertFieldsSql += ",[" + fieldName + "]";
insertValuesSql += ",@" + fieldName;
}
}

//UPDATE SQL
if (isPrimaryField)
{
if (updateWhereSql == string.Empty)
{
updateWhereSql = " WHERE [" + fieldName + "] = @" + fieldName;
}
else
{
updateWhereSql += " AND [" + fieldName + "] = @" + fieldName;
}
}
else if (!isAutoIncrementField)
{
if (updateSetSql == string.Empty)
{
updateSetSql = " SET [" + fieldName + "] = @" + fieldName;
}
else
{
updateSetSql += ",[" + fieldName + "] = @" + fieldName;
}
}
string parameterName = "@" + fieldName;
m_DalCachedParameters.Add(parameterName, CreateSqlParameterByProperty(propertyInfo, parameterName));
}
}

if (m_PrimaryFieldPropertyInfo == null)
{
throw new ApplicationException("Miss Primary Field defination");
}

m_InsertSql = "INSERT " + m_TableName + " (" + insertFieldsSql + ")" + " VALUES(" + insertValuesSql + ")";
m_UpdateSql = "UPDATE " + m_TableName + updateSetSql + updateWhereSql;
}
#endregion

#region
protected void OpenConnection()
{
if (m_DalConnection.State == System.Data.ConnectionState.Closed)
{
m_DalConnection.Open();
}
}

protected void CloseConnection()
{
if (m_DalConnection.State == System.Data.ConnectionState.Open)
{
m_DalConnection.Close();
}
}

public DataTable GetTemplateDataTable()
{
if (m_TemplateDataTable == null)
{
try
{
OpenConnection();

m_DalCommand.Parameters.Clear();
m_DalCommand.CommandText = "SELECT TOP 0 " + m_SelectSql + " FROM " + m_TableName;
SqlDataAdapter daDataAdapter = new SqlDataAdapter(m_DalCommand);

DataTable result = new DataTable();
daDataAdapter.Fill(result);
m_TemplateDataTable = result;
}
finally
{
CloseConnection();
}
}

return m_TemplateDataTable.Clone();
}

public void BulkCopyDataTable(DataTable dataTable)
{
try
{
OpenConnection();

SqlBulkCopy daBulkCopy = new SqlBulkCopy(m_DalConnection);
daBulkCopy.BulkCopyTimeout = 10000;
daBulkCopy.DestinationTableName = "[" + m_TableName + "]";
daBulkCopy.WriteToServer(dataTable);
}
finally
{
CloseConnection();
}
}
#endregion

#region
protected Int32 CountObjects(String where)
{
Int32 result = 0;
try
{
OpenConnection();

m_DalCommand.CommandText = "SELECT COUNT(*) FROM " + m_TableName + " " + where;
result = Convert.ToInt32(m_DalCommand.ExecuteScalar());
}
finally
{
CloseConnection();
}

return result;
}

protected List<T> SelectObjects(String where)
{
return SelectObjects(where, String.Empty, String.Empty, String.Empty);
}

protected List<T> SelectObjects(String where, String with)
{
return SelectObjects(where, with, String.Empty, String.Empty);
}

protected List<T> SelectObjects(String where, String with, String order)
{
return SelectObjects(where, with, String.Empty, order);
}

protected List<T> SelectObjects(String where, String with, String top, String order)
{
List<T> objects = new List<T>();
try
{
OpenConnection();

m_DalCommand.CommandText = "SELECT " + top + " " + m_SelectSql + " FROM " + m_TableName + " " + with + " " + where + order;
using (SqlDataReader dataReader = m_DalCommand.ExecuteReader())
{
while (dataReader.Read())
{
objects.Add(ReadObjectFromDataReader(dataReader));
}
}
}
finally
{
CloseConnection();
}

return objects;
}

protected Int32 DeleteObjects(String where)
{
try
{
OpenConnection();

m_DalCommand.CommandText = "DELETE FROM " + m_TableName + " " + where;
return m_DalCommand.ExecuteNonQuery();
}
finally
{
CloseConnection();
}
}

protected Int32 InsertObject(T obj)
{
try
{
OpenConnection();

m_DalCommand.CommandText = m_InsertSql;
m_DalCommand.Parameters.Clear();
foreach (String key in m_CachedFieldPropertyInfo.Keys)
{
m_DalCachedParameters["@" + key].Value = m_CachedFieldPropertyInfo[key].GetValue(obj, null);
m_DalCommand.Parameters.Add(m_DalCachedParameters["@" + key]);
}
int count = m_DalCommand.ExecuteNonQuery();

if (count > 0 && m_AutoIncrementFieldPropertyInfo != null)
{
m_DalCommand.CommandText = "SELECT @@IDENTITY";
m_DalCommand.Parameters.Clear();
Object ObjID = m_DalCommand.ExecuteScalar();
SetValueForProperty(m_AutoIncrementFieldPropertyInfo, obj, ObjID);
}

obj.IsLoad = count > 0;

return count;
}
finally
{
CloseConnection();
}
}

protected Int32 UpdateObject(T obj)
{
try
{
OpenConnection();

m_DalCommand.CommandText = m_UpdateSql;

m_DalCommand.Parameters.Clear();
foreach (String key in m_CachedFieldPropertyInfo.Keys)
{
m_DalCachedParameters["@" + key].Value = m_CachedFieldPropertyInfo[key].GetValue(obj, null);
m_DalCommand.Parameters.Add(m_DalCachedParameters["@" + key]);
}

int count = m_DalCommand.ExecuteNonQuery();

obj.IsLoad = count > 0;

return count;
}
finally
{
CloseConnection();
}
}
#endregion

#region
private T ReadObjectFromDataReader(SqlDataReader dataReader)
{
T result = (T)Activator.CreateInstance(typeof(T));

foreach (String key in m_CachedFieldPropertyInfo.Keys)
{
SetValueForProperty(m_CachedFieldPropertyInfo[key], result, dataReader[key]);
}

result.IsLoad = true;

return result;
}

private void SetValueForProperty(PropertyInfo propertyInfo, object obj, object value)
{
switch (propertyInfo.PropertyType.FullName)
{
case "System.String":
propertyInfo.SetValue(obj, value as string, null);
break;
case "System.Int32":
propertyInfo.SetValue(obj, Convert.ToInt32(value), null);
break;
case "System.Boolean":
propertyInfo.SetValue(obj, (bool)value, null);
break;
case "System.DateTime":
propertyInfo.SetValue(obj, (DateTime)value, null);
break;
}
}

private SqlParameter CreateSqlParameterByProperty(PropertyInfo propertyInfo, string parameterName)
{
switch (propertyInfo.PropertyType.FullName)
{
case "System.String":
return new SqlParameter(parameterName, SqlDbType.VarChar);
case "System.Int32":
return new SqlParameter(parameterName, SqlDbType.Int);
case "System.Boolean":
return new SqlParameter(parameterName, SqlDbType.Bit);
case "System.DateTime":
return new SqlParameter(parameterName, SqlDbType.DateTime);
default:
return null;
}
}
#endregion
}
}

2.応用
プロジェクトエンティティークラスを定義するには、次の手順に従います.
using System;
using Core;

namespace Entity
{
[Serializable]
[TableMapping(TableName="tabProject")]
public class Project:EntityBase
{
String projectID = string.Empty;
[FieldMapping(FieldName = "ProjectID",IsPrimary=true)]
public String ProjectID
{
get { return projectID; }
set { IsDirty |= (projectID != value); projectID = value; }
}

String projectName = string.Empty;
[FieldMapping(FieldName = "ProjectName")]
public String ProjectName
{
get { return projectName; }
set { IsDirty |= (projectName != value); projectName = value; }
}
}
}

ProjectServiceデータアクセスクラスを定義します.
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using Core;
using Entity;

namespace Service
{
public class ProjectService : ServiceBase<Project>
{
#region
const String SQL_WHERE_ID = "WHERE ProjectID = @ProjectID";
const String SQL_PARAM_PROJECTID = "@ProjectID";
const String SQL_PARAM_PROJECTNAME = "@ProjectName";
#endregion

#region
public ProjectService(SqlConnection sqlConnection)
: base(sqlConnection)
{
}
#endregion

#region
public Project GetProjectByID(String projectID)
{
m_DalCommand.Parameters.Clear();
m_DalCachedParameters[SQL_PARAM_PROJECTID].Value = projectID;
m_DalCommand.Parameters.Add(m_DalCachedParameters[SQL_PARAM_PROJECTID]);
List<Project> projects = base.SelectObjects(SQL_WHERE_ID);
return projects.Count > 0 ? projects[0] : null;
}
public List<Project> GetAllProjects()
{
m_DalCommand.Parameters.Clear();
return base.SelectObjects(string.Empty);
}
#endregion

#region
public Int32 InsertProject(Project project)
{
return base.InsertObject(project);
}
public Int32 UpdateProject(Project project)
{
return base.UpdateObject(project);
}
#endregion

#region
public Int32 DeleteProjectByID(String projectID)
{
m_DalCommand.Parameters.Clear();
m_DalCachedParameters[SQL_PARAM_PROJECTID].Value = projectID;
m_DalCommand.Parameters.Add(m_DalCachedParameters[SQL_PARAM_PROJECTID]);

return base.DeleteObjects(SQL_WHERE_ID);
}
#endregion
}
}

次の操作を行います.
Get:
ProjectService ps = new ProjectService(new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=Database1;Integrated Security=True"));
List<Project> projects = ps.GetAllProjects();

Insert:
ProjectService projectService = new ProjectService(new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=Database1;Integrated Security=True")); 
Project project = new Project();
project.ProjectID = "1000";
project.ProjectName = "Test";
projectService.InsertProject(project);

Update:
ProjectService projectService = new ProjectService(new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=Database1;Integrated Security=True")); 
Project project = new Project();
project.ProjectID = "1000";
project.ProjectName = "Hello";
projectService.UpdateProject(project);

Delete:
ProjectService projectService = new ProjectService(new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=Database1;Integrated Security=True")); 
projectService.DeleteProjectByID("1000");