最近公司项目开动了,出于各种考虑还是相对保守的采用 .NET 2.0 + 企业库 + SQLSERVER的大体框架.
为了封装单个实体对象的CRUD操作,遂自己动手写了一个orm实现的工具类库. ...
最近公司项目开动了,出于各种考虑还是相对保守的采用 .NET 2.0 + 企业库 + SQLSERVER的大体框架.
为了封装单个实体对象的CRUD操作,遂自己动手写了一个orm实现的工具类库.
-------------------------------------------------------------------------------------------------------
首先,我们声明一个实体接口 IEntity
public interface IEntity : ICloneable


{

int ID
{ get; set; }

bool IsPersisted
{ get; }

IEntity
{ get; }
}

根据图示, IEntity接口实现ICloneable接口, 并且有三个属性
ID : 对应每个实体类型所对应的数据库表的主键ID (有一个前言约定: 所有表的主键id均为自增标识)
IsPersisted : 指示对象是否已持久化(对应到数据库表的一条记录)
Raw : 返回对象实例的已持久化的原始状态
有了实体,如何mapping到具体哪个数据表呢 ?
"约定优于配置", 因此我们直接使用Attribute来实现
public class EntityMappingAttribute : Attribute

{
private string _tableName;
public string TableName

{

get
{ return _tableName; }

set
{ _tableName = value; }
}

public EntityMappingAttribute(string tableName)

{
TableName = tableName;
}

}
同理,为了建立实体Property到数据表字段的对应关系我们新建PropertyMappingAttribute类
public class PropertyMappingAttribute : Attribute

{
private string _fieldName;

public string FieldName

{

get
{ return _fieldName; }

set
{ _fieldName = value; }
}


public PropertyMappingAttribute()
{ }

public PropertyMappingAttribute(string fieldName)

{
FieldName = fieldName;
}

}
经过上述处理, 一个十分简单的面向对象实体(Object)到关系型数据表(Relationship)的映射(Mapping)就已经声明完毕了.
既然前面声明了IEntity接口, 理所当然的我们应该实现它
public abstract class EntityBase : IEntity

{
private IEntity _raw;
private int _id;
private bool _isPersisted = false;


IEntity Members#region IEntity Members

/**//// <summary>
/// ID
/// </summary>
public virtual int ID

{

get
{ return _id; }

set
{ _id = value; }
}


public virtual IEntity Raw

{

get
{ return _raw; }

protected set
{ _raw = value; }
}



/**//// <summary>
/// 该对象是否已持久化
/// </summary>
public virtual bool IsPersisted

{

get
{ return _isPersisted; }

protected set
{ _isPersisted = value; }
}
#endregion



ICloneable Members#region ICloneable Members

public object Clone()

{
Type type = this.GetType();

object obj = Activator.CreateInstance(type);

foreach (PropertyInfo p in type.GetProperties())

{
object value = p.GetValue(this,null);
p.SetValue(obj, value, null);
}

return obj;
}

#endregion
}
由于IEntity 实现了ICloneable接口, 实际上肩负重任的抽象类EntityBase需要实现两个接口.
因为我们不能向外界暴露设置实体是否持久化和原始状态的信息的设置器, 我们把set修饰为protected.
而实现ICloneable比较简单,就是利用反射构造出一个当前实体对象实例的拷贝.
基础工作差不多了, 让我们我们新建一个User
[Serializable]
[EntityMapping("t_user")]
public class User : EntityBase


{
[PropertyMapping]

public string Name
{ get;set;}
public string Hello

{

get
{ return "hello, I am "+Name;}
}
}
从前面的介绍可以知道,存在一个t_user表(字段有id,name),我们用User类来对应.
东西已经有了,如何使用是关键. 第一步我们要实现的是简单的Crud操作, 先声明一下管理这些操作的接口 IEntityManager
public interface IEntityManager

{
T Create<T>(T t) where T : IEntity;
void Update<T>(T t) where T : IEntity;
T Load<T>(int id) where T : IEntity;
void Delete<T>(int id) where T : IEntity;
List<T> LoadAll<T>() where T : IEntity;
}

在这里我们声明了几个泛型方法用来实现管理实体对象,并且约束其传入的参数必须实现我们上面声明IEntity接口
--------------------------------------------------
下一节,我们将完成IEntityManager是如何去实现管理实体的功能.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构