您的位置:首页 > 其它

一步步实现自己的ORM(四)

2015-03-30 17:31 302 查看
通过前3章文章,大致对ORM有一定的了解,但也存在效率低下(大量用了反射)和重复代码,今天我们要对ORM进行优化。

具体流程如下:

class DbContext
{
private DbProvider dbProvider;
private DbSqlBuilder sqlBuilder ;

public DbContext(string connectionString)
{
SqlConnection conn = new SqlConnection(connectionString);
dbProvider = new DbProvider(conn);
this.sqlBuilder = new DbSqlBuilder();
}

public int Insert<T>(object entity)
{
var entityMapping = AttributeMapping.Get<T>();

//将Entity转换成Dictionary
var parameters = DynamicMethodBuilder.ConvertFromObject(entity);
var sql = sqlBuilder.BuildInsertSql(entityMapping, parameters.Keys.ToList());
return dbProvider.ExecuteNonQuery(sql, parameters);
}

public int Update<T>(T entity)
{
var entityMapping = AttributeMapping.Get<T>();
//将Entity转换成Dictionary
var parameters = DynamicMethodBuilder.ConvertFromObject(entity);
var columns = entityMapping.Members.Where(m => m.IsDbGenerated == false && m.IsPrimaryKey == false).Select(c => c.ColumnName).ToArray();
var updateColumns = new Dictionary<string, object>();
var whereColumns = new Dictionary<string, object>();

foreach (var item in parameters)
{
if (columns.Contains(item.Key))
updateColumns.Add(item.Key, item.Value);
if (entityMapping.PrimaryKey.All(m => m.ColumnName == item.Key))
whereColumns.Add(item.Key, item.Value);
}

var sql = sqlBuilder.BuildUpdateSql(entityMapping, updateColumns.Keys.ToList(), whereColumns.Keys.ToList());

return dbProvider.ExecuteNonQuery(sql, parameters);
}

public int DeleteByKey<T>(params object[] values)
{
var entityMapping = AttributeMapping.Get<T>();

if (values.Length != entityMapping.PrimaryKey.Count)
throw new ArgumentException("参数个数和主键数不一致");

var parameters = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < entityMapping.PrimaryKey.Count; i++)
{
parameters.Add(entityMapping.PrimaryKey[i].ColumnName, values[i]);
}

var sql = sqlBuilder.BuildDeleteSql(entityMapping, parameters.Keys.ToList());

return dbProvider.ExecuteNonQuery(sql, parameters);
}

public T Get<T>(object[] values)
{
var entityMapping = AttributeMapping.Get<T>();

if (values.Length != entityMapping.PrimaryKey.Count)
throw new ArgumentException("参数个数和主键数不一致");

var parameters = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

StringBuilder where = new StringBuilder();

for (int i = 0; i < values.Length; i++)
{
if (i > 0) //考虑到有多个主键
where.Append(" AND ");

where.Append(entityMapping.PrimaryKey[i].ColumnName).Append("=").Append("@p").Append(i);

/*参数*/
parameters.Add("@p" + i, values[i]);
}

var sql = this.sqlBuilder.BuildSelectSql(entityMapping, where.ToString(), string.Empty);

return GetEntityList<T>(sql, parameters).FirstOrDefault();
}

public List<T> GetList<T>(string where, string orderBy)
{
var entityMapping = AttributeMapping.Get<T>();

var sql = this.sqlBuilder.BuildSelectSql(entityMapping, where.ToString(), orderBy);

return GetEntityList<T>(sql, null);
}

public List<T> GetEntityList<T>(string sql, Dictionary<string, object> parameters)
{

var reader = dbProvider.ExecuteReader(sql, parameters);
List<T> list = new List<T>();
var type = typeof(T);
var properties = type.GetProperties();
while (reader.Read())
{
var user = Activator.CreateInstance(type);
for (int i = 0; i < properties.Length; i++)
{
var pi = properties[i];
if (reader[pi.Name] != null) //等同于 if (reader["UserId"] != null)这样的语句
pi.SetValue(user, reader[pi.Name], null); //等同于 user.UserId = (int)reader["UserId"];
}

list.Add((T)user);
}
return list;
}
}


View Code
本章结束,下一章要将DataReader转换成实体类的代码优化。

下载地址:http://files.cnblogs.com/files/sobaby/ORM04.zip
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: