`

利用attribute实现简单的ORM

阅读更多

  我不知道NH的ORM具体如何实现的,我的想法就是通过字段名称和属性名称的对应关系来实现赋值。

  简单的类型比较好做,直接赋值就可以了。简单类型是说int,string之类的。

  有几个需要注意的地方:

  1 属性的类型是另外一个类

  2 属性是一个集合

  3 类有两个属性的类型是同一个类,例如:种子有用量及其单位,和产量及其单位,用量的单位和产量的单位是一个类型

  4 属性嵌套,就是属性的这个类型里面的属性还可能是另外一个类

  

  解决办法:

  1 用不同的attribute,普通的类型直接赋值,另外一个类的话就交给另外一个类去负责具体的映射

  2 分两次映射,然后集合赋值给商品的属性,觉得不是很好,有没有更好的办法呢?

  3 添加前缀来区分两个相同类型的不同属性

  4 嵌套,一层一层解决

  还有就是关于集合,例如:商品的包装规格集合。如何映射呢?是不是需要集合的时候,再次根据商品的ID查询包装规格集合,然后赋值给商品的包装规格属性呢?

  那就是两次访问数据库了,我想要一次访问,可以实现吗?

  结果集就是下面的格式,第一个table是商品,第二个table是包装规格,循环第一个table映射出来一个商品,但是在映射的时候如果发现属性是List类型,实际上是需要第二个结果集来配合了。如何传第二个的结果集呢?我想不出来。我的解决办法就是一个一个的映射,先映射商品,赋值给一个商品的实例。然后映射包装规格,赋值给一个List,然后把这个List赋值给商品的包装规格属性。

  不知道能否在映射商品的同时就映射包装规格集合吗?

  

  数据库的查询结果

  

 

  先定义两个attribute,一个用在属性上面,用来映射列

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.SQLite.ConApp.Common
{
    [AttributeUsage(AttributeTargets.Property)]
    
public class ColumnAttribute : Attribute
    {
        
private string _columnType;
        
/// <summary>
        
/// 数据库字段类型
        
/// </summary>
        public string ColumnType
        {
            
get { return _columnType; }
            
set { _columnType = value; }
        }
        
private string _columnName;
        
/// <summary>
        
/// 数据库字段名称
        
/// </summary>
        public string ColumnName
        {
            
get { return _columnName; }
            
set { _columnName = value; }
        }
        
private int _length;
        
/// <summary>
        
/// 数据库字段长度
        
/// </summary>
        public int Length
        {
            
get { return _length; }
            
set { _length = value; }
        }
        
private bool _isIdentity;
        
/// <summary>
        
/// 是否标识列
        
/// </summary>
        public bool IsIdentity
        {
            
get { return _isIdentity; }
            
set { _isIdentity = value; }
        }

        
public ColumnAttribute(string columnName, string columnType, int len, bool isIdentity)
        {
            
this._columnType = columnType;
            
this._columnName = columnName;
            
this._length = len;
            
this._isIdentity = isIdentity;
        }
        
public ColumnAttribute(string columnName)
            : 
this(columnName, string.Empty, 0false)
        {

        }
    }
}

  一个用在属性是复杂类型,也就是说属性的类型是另外一个类

  

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.SQLite.ConApp.Common
{
    [AttributeUsage(AttributeTargets.Property)]
    
public class ReferenceAttribute : Attribute
    {
        
private Type _referenceClassType;

        
public Type ReferenceClassType
        {
            
get { return _referenceClassType; }
            
set { _referenceClassType = value; }
        }
        
private string _preFix;

        
public string PreFix
        {
            
get { return _preFix; }
            
set { _preFix = value; }
        }

        
private ReferenceType _referenceType;

        
public ReferenceType ReferenceType
        {
            
get { return _referenceType; }
            
set { _referenceType = value; }
        }
        
public ReferenceAttribute(Type type, string preFix,ReferenceType referenceType)
        {
            
this._referenceClassType = type;
            
this._preFix = preFix;
            
this._referenceType = referenceType;
        }

    }
    
public enum ReferenceType
    {
        Ojbect,
        Collection
    }
}

 

  给这两种attribute类型定义两个映射方法

  

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->public  class ColumnMapper
    {
       
public static void ColToProperty(ref PropertyInfo p,object entity, IDataReader reader,string preFix)
       {
           
string columnName = string.IsNullOrWhiteSpace(preFix) ? p.Name : preFix + p.Name;
          
               
if (p.PropertyType.IsEnum)
               {
                   p.SetValue(entity, Enum.Parse(p.PropertyType, reader[columnName].ToString()), 
null);
               }
               
else
               {
                   p.SetValue(entity, reader[columnName], 
null);
               }
          
       }
    }

 
public class ReferenceMapper
    {
        
public static object   ReferenceToEntity( Type type, string preFix, IDataReader  reader, Common.ReferenceType referenceType)
        {
            
string columnName = string.Empty;
           
object obj = Activator.CreateInstance(type);

            PropertyInfo[] ps 
= obj.GetType ().GetProperties();

            
for (int i = 0; i < ps.Length; i++)
            {
                columnName 
= string.IsNullOrWhiteSpace(preFix) ? ps[i].Name : preFix + ps[i].Name;
                
object[] attributes = ps[i].GetCustomAttributes(false);
                
if (attributes.Length > 0)
                {
                    
if (referenceType == Common.ReferenceType.Ojbect)
                    {
                        
if (attributes[0is Common.ColumnAttribute)
                        {
                            
if (string.IsNullOrWhiteSpace(reader[columnName].ToString()))
                                
continue;
                            ColumnMapper.ColToProperty(
ref ps[i], obj, reader, preFix);
                        }
                        
if (attributes[0is Common.ReferenceAttribute)
                        {
                            ps[i].SetValue(obj, ReferenceMapper.ReferenceToEntity((attributes[
0as Common.ReferenceAttribute).ReferenceClassType,
                               (attributes[
0as Common.ReferenceAttribute).PreFix, reader, (attributes[0as Common.ReferenceAttribute).ReferenceType), null);
                        }
                    }
                }
            }
            
return obj;
        }
    }

 

  实例实体类

  

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--> [Flags]
    
public enum ProductType
    {
        Seed 
= 1,
        Fertilizer 
= 2,
        Pesticide 
= 4
    }
    
public class Seed : Common.BaseEntity
    {
        [Column(
"SeedID")]
        
public Guid SeedID
        { 
getset; }
        [Column(
"SeedName")]
        
public string SeedName
        { 
getset; }
        [Column (
"ProductType")]
        
public ProductType ProductType
        {
            
get;
            
set;
        }
        [Column(
"PlantAmount")]
        
public decimal PlantAmount
        { 
getset; }
        [Reference(
typeof(Unit), "PlantAmount", Common.ReferenceType.Ojbect )]
        
public Unit PlantAmountUnit
        { 
getset; }
        [Column(
"OutputAmount")]
        
public decimal OutputAmount
        { 
getset; }
        [Reference(
typeof(Unit), "OutputAmount", Common.ReferenceType.Ojbect )]
        
public Unit OutputAmountUnit
        { 
getset; }
        
//[Reference (typeof(SeedPkgSpec),"", Common.ReferenceType.Collection )]
        public List<SeedPkgSpec> PkgSpecs
        {
            
get;
            
set;
        }
    }

 

SeedPkgSpec
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeautyCode.SQLite.ConApp.Common;

namespace BeautyCode.SQLite.ConApp.Entity
{
    
public class SeedPkgSpec : Common.BaseEntity 
   {
       [Column(
"PkgSpecID")]
       
public Guid PkgSpecID
       { 
getset; }
       [Column(
"SeedID")]
       
public Guid SeedID 
       { 
getset; }
       [Column(
"PkgAmount")]
       
public decimal PkgAmount
       { 
getset; }
       [Reference(
typeof(Unit ),"PkgAmount", Common.ReferenceType.Ojbect ) ]
       
public Unit PkgUnit
       { 
getset; }
       [Reference(
typeof(PkgSpec), "",  Common.ReferenceType.Ojbect )]
       
public PkgSpec PkgSpec
       {
           
get;
           
set;
       }
    }
}

 

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeautyCode.SQLite.ConApp.Common;

namespace BeautyCode.SQLite.ConApp.Entity
{
   
public  class PkgSpec:Common.BaseEntity 
    {
       [Column(
"PkgSpecCode")]
       
public string PkgSpecCode
       { 
getset; }
       [Column(
"PkgSpecName")]
       
public string PkgSpecName
       { 
getset; }
    }
}

 

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BeautyCode.SQLite.ConApp.Common;

namespace BeautyCode.SQLite.ConApp.Entity
{
    
public class Unit : Common.BaseEntity 
    {
        [Column(
"UnitCode")]
        
public string UnitCode 
        { 
getset; }
        [Column(
"UnitCnName")]
        
public string UnitCnName
        { 
getset; }
        [Column( 
"UnitEnName")]
        
public string UnitEnName
        { 
getset; }
    }
}

  映射接口,每个实体实现下面的接口

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;


namespace BeautyCode.SQLite.ConApp.EntityMapper
{
    
public interface  IEntityMapper<T> where T:Common.BaseEntity 
    {
        T RowToEntity(IDataReader  reader);

        DataRow EntityToRow(T entity);
    }
}

 

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;

namespace BeautyCode.SQLite.ConApp.EntityMapper
{
    
public class SeedMapper : IEntityMapper<Entity.Seed>
    {
        
#region IEntityMapper<Seed> Members

        
public Entity.Seed RowToEntity(IDataReader reader)
        {
            Entity.Seed entity 
= new Entity.Seed();

            PropertyInfo[] ps 
= typeof(Entity.Seed).GetProperties();

            
for (int i = 0; i < ps.Length; i++)
            {
                
object[] attributes = ps[i].GetCustomAttributes(false);
                
if (attributes.Length > 0)
                {
                    
if (attributes[0is Common.ColumnAttribute)
                    {
                        ColumnMapper.ColToProperty(
ref ps[i], entity, reader, null);
                    }
                    
if (attributes[0is Common.ReferenceAttribute)
                    {
                        ps[i].SetValue(entity, ReferenceMapper.ReferenceToEntity((attributes[
0as Common.ReferenceAttribute).ReferenceClassType,
                             (attributes[
0as Common.ReferenceAttribute).PreFix, reader, (attributes[0as Common.ReferenceAttribute).ReferenceType), null);

                    }
                }

            }
            
return entity;
        }



        
public System.Data.DataRow EntityToRow(Entity.Seed entity)
        {
            
throw new NotImplementedException();
        }

        
#endregion
    }
}

 

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;

namespace BeautyCode.SQLite.ConApp.EntityMapper
{
    
public class SeedPkgSpecMapper:IEntityMapper<Entity.SeedPkgSpec >
    {
        
#region IEntityMapper<SeedPkgSpec> Members

        
public Entity.SeedPkgSpec RowToEntity(IDataReader  reader)
        {
            Entity.SeedPkgSpec entity 
= new Entity.SeedPkgSpec();

            PropertyInfo[] ps 
= typeof(Entity.SeedPkgSpec).GetProperties();

            
for (int i = 0; i < ps.Length; i++)
            {
                
object[] attributes = ps[i].GetCustomAttributes(false);
                
if (attributes.Length > 0)
                {
                    
if (attributes[0is Common.ColumnAttribute)
                    {
                        
if (string.IsNullOrWhiteSpace(reader[ps[i].Name].ToString()))
                            
continue;
                        ColumnMapper.ColToProperty(
ref ps[i], entity, reader, null);
                    }
                    
if (attributes[0is Common.ReferenceAttribute)
                    {
                        ps[i].SetValue(entity, ReferenceMapper.ReferenceToEntity((attributes[
0as Common.ReferenceAttribute).ReferenceClassType,
                             (attributes[
0as Common.ReferenceAttribute).PreFix, reader, (attributes[0as Common.ReferenceAttribute).ReferenceType), null);

                    }
                }

            }
            
return entity;
        }

        
public System.Data.DataRow EntityToRow(Entity.SeedPkgSpec entity)
        {
            
throw new NotImplementedException();
        }

        
#endregion
    }
}

 

 

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace BeautyCode.SQLite.ConApp.EntityMapper
{
    
public class UnitMapper:IEntityMapper<Entity.Unit>
    {
        
#region IEntityMapper<Unit> Members

        
public Entity.Unit RowToEntity(System.Data.IDataReader reader)
        {
            Entity.Unit entity 
= new Entity.Unit();

            PropertyInfo[] ps 
= typeof(Entity.Unit).GetProperties();

            
for (int i = 0; i < ps.Length; i++)
            {
                
object[] attributes = ps[i].GetCustomAttributes(false);
                
if (attributes.Length > 0)
                {
                    
if (attributes[0is Common.ColumnAttribute)
                    {
                        
if (string.IsNullOrWhiteSpace(reader[ps[i].Name].ToString()))
                            
continue;
                        ColumnMapper.ColToProperty(
ref ps[i], entity, reader, null);
                    }
                    
if (attributes[0is Common.ReferenceAttribute)
                    {
                        ps[i].SetValue(entity, ReferenceMapper.ReferenceToEntity((attributes[
0as Common.ReferenceAttribute).ReferenceClassType,
                             (attributes[
0as Common.ReferenceAttribute).PreFix, reader, (attributes[0as Common.ReferenceAttribute).ReferenceType), null);

                    }
                }

            }
            
return entity;
        }

        
public System.Data.DataRow EntityToRow(Entity.Unit entity)
        {
            
throw new NotImplementedException();
        }

        
#endregion
    }
}

 

  上面的代码结构其实还是可以优化的,因为每个实体类的映射方法,里面的代码大量的重复,只是初始化的类型不一样,还有重构的余地。

  目前还差的就是映射集合,在映射商品的时候一起映射集合。

  项目可以从http://beautycode.codeplex.com/下载,或者是/Files/virusswb/BeautyCode.SQLite.ConApp.rar

分享到:
评论

相关推荐

    Laravel开发-attribute-manipulation

    在Laravel框架中,属性操纵(Attribute Manipulation)是模型(Eloquent ORM)的一个关键特性,它使得开发者能够轻松地处理数据库数据的读取、设置和格式化。本教程将深入探讨这一主题,帮助你更好地理解和利用这个...

    Attribute 学习

    这些Attribute在运行时可以通过反射(Reflection)来读取和利用,从而实现各种自定义逻辑。例如,`[Serializable]` Attribute用于标记一个类为可序列化的,`[DataContract]`和`[DataMember]`在WCF(Windows ...

    利用AOP实现SqlSugar自动事务

    利用AOP实现SqlSugar自动事务 AOP(Aspect-Oriented Programming,面向方面编程)是一种软件开发技术,旨在将横切关注点与业务逻辑分离,以提高代码的可维护性和可扩展性。在本文中,我们将使用AOP技术来实现...

    C#特性标签实现通用Dao层

    本篇将重点探讨如何利用C#的特性(Attribute)标签来实现这一目标,同时结合反射(Reflection)技术,以提高代码的可复用性和可维护性。 首先,让我们了解C#中的特性(Attribute)。特性是一种元数据,可以附加到...

    .net反射与特性的使用方法

    本文将深入探讨这两个概念以及如何在实际应用程序中有效地利用它们。 首先,我们来理解什么是反射。反射是.NET框架的一个核心特性,它允许程序在运行时检查自身的信息,如类型、属性、方法等,并能动态地创建对象和...

    20191118属性类扩展.zip

    本文将深入探讨“20191118属性类扩展.zip”这个压缩包中涉及的C# ORM实体类属性扩展和属性过滤器的实现,以及如何利用`partial`、`virtual`和`override`等关键字来增强代码的灵活性和可维护性。 首先,让我们了解...

    NBearV3.7.2.11

    自定义Attribute的支持进一步增强了框架的灵活性,使得开发者可以根据具体需求进行定制,实现更加精细化的控制。通过深入学习和利用NBear的源代码,开发者可以提升自己的技术水平,并为项目带来更多的可能性。

    用JSP实现XML文件到Oracle数据库的导入和导出.pdf

    - **工具包**:`org.jdom`是JDOM的主要工具包,提供了Document、Element、Comment、DocType、Attribute、Text等类用于操作JDOM文档。 ##### 2.2 环境配置 环境配置步骤如下: 1. **安装JDK1.6.0**:设置系统变量...

    Laravel开发-eloquent-custom .zip

    Eloquent ORM采用ActiveRecord设计模式,使得与数据库交互变得简单且直观。在这个"**Laravel开发-eloquent-custom**"的资料中,我们很可能会学习到如何自定义Eloquent模型,扩展其功能,以及如何更高效地利用它来...

    基于 Echo + Gorm + Casbin + Uber-FX 实现的 RBAC 权限-echo-admin.zip

    综上所述,"echo-admin"项目利用了Echo、Gorm、Casbin和可能的Uber-FX技术,构建了一个功能完善的RBAC系统,实现了用户角色的划分、权限的定义与管理,以及基于这些信息的访问控制决策,确保了系统的安全性与效率。...

    C#通用权限

    2. Entity Framework等ORM工具可以方便地与数据库交互,实现动态的角色和菜单权限管理。 总结,C#通用权限系统的设计和实现涉及到多个层面,包括UI的菜单权限和业务逻辑的方法权限。通过合理地运用.NET框架提供的...

    Laravel开发-dynamodb

    标题"laravel-dynamodb"表明我们将在 Laravel 开发环境中应用 DynamoDB,而描述提及了"dynamodb 的雄辩语法",暗示我们将学习如何利用 Laravel 的 Eloquent ORM(对象关系映射)与 DynamoDB 进行交互。 首先,...

    ios-CoreData实现的增删改查.zip

    Core Data是Apple提供的一种强大的数据管理框架,用于实现对象关系映射(ORM),方便地进行数据的本地化存储。本教程将深入探讨如何利用Core Data在iOS应用中实现数据的增删改查操作。 首先,让我们了解一下Core ...

    基于RemObjects持久层系统

    此外,还可以定义关系映射,如一对一、一对多或多对多的关系,通过`ReferenceAttribute`或`ListAttribute`实现。 在数据访问方面,RemObjects提供了一个直观的API,可以方便地进行数据操作。例如,`DataSession`...

    hibernate-jpa-2.1-api-1.0.0.final-sources.jar.zip

    通过阅读和分析这些源代码,开发者不仅可以理解JPA 2.1规范,还能了解到Hibernate如何优雅地实现了这些规范,从而在实际项目中更好地利用Hibernate的功能,提高开发效率。同时,源码阅读也有助于提升问题排查和性能...

    Meta-Attribute Object Store-开源

    元属性对象存储,简称MAOS,是一种基于Java的轻量级库和框架,旨在提供一种高效且简单的方式来实现对象的持久化。它借鉴了搜索引擎技术,使得数据存储和检索更为便捷。在IT领域,持久化是将应用程序中的对象状态保存...

    symfony-attribute-demo:一个小型演示项目,用于使用Symfony测试PHP属性

    3. **Entities**:实体类可能会利用 PHP 属性进行类型提示,提高数据验证和ORM(对象关系映射)如 Doctrine 的效率。 4. **Routing**:项目可能包含一个 `routes.yaml` 文件,其中定义了路由,而某些路由可能会引用...

    特性与反射得出sql语句

    总结,特性(Attribute)和反射(Reflection)是C#中强大的工具,它们结合使用可以实现灵活的代码设计和动态行为。在这个“特性与反射得出SQL语句”的示例中,我们看到了如何通过自定义特性标注方法,然后使用反射来...

    oracle自动生成实体类-链接DLinq--源码

    本程序正是利用DLinq,实现了自动生成Oracle数据库中的表对应的实体类代码,大大减少了手动编写这些类的工作量,提高了开发效率。 DLinq(Dapper.LINQ)是基于Dapper的扩展,它提供了类似于Entity Framework的LINQ...

    开源框架介绍

    同时,这也是一个很好的机会去探索.NET框架下的编程实践,例如使用特性(Attribute)进行元数据标记,以及如何利用反射进行对象属性的映射。 总的来说,开源框架如Dapper为开发者带来了极大的便利,通过研究和使用...

Global site tag (gtag.js) - Google Analytics