LLBL Gen Pro是一款优秀的对象关系映射开发框架,自2003年发布以来,一直有广泛的客户群。LLBL Gen Pro有几个标志性的版本,2.5/2.6是一个很稳定的版本,公司的一些旧的项目仍然用的是这个版本。3.1 将项目的文件改成XML格式(llblgenproj),极大的方便和简化了第三方工具与LLBL Gen交互,我的项目中用到的代码生成模板即使借助于解析它的XML格式文件,生成接口与实现文件。3.1也修改了生成实体的参数的顺序。比如2.5/2.6版本的送货单明细实体的代码如下:

public ShipmentDetailEntity(System.String refNo,System.Decimal entryNo):base("ShipmentDetailEntity")
{
       InitClassEmpty(null, null);
       this.Fields["EntryNo"].CurrentValue = entryNo;
       this.Fields["RefNo"].CurrentValue = refNo;
}

3.1则会生成如下的代码

public ShipmentDetailEntity(System.Decimal entryNo, System.String refNo):base("ShipmentDetailEntity")
{
       InitClassEmpty(null, null);
       this.Fields["EntryNo"].CurrentValue = entryNo;
       this.Fields["RefNo"].CurrentValue = refNo;
}

注意看两个构造方法的参数顺序有差异,2.x是以数据库中主键定义的顺序生成构造方法,3.1则是以主键的字母顺序为参数排列依据。

再到LLGL Gen Pro 3.5,3.5 抛弃了传统的EntityCollection,不再维护EntityCollection设计模式,而选用微软推荐的BindingSource控件,直接将BindingSource控件绑定到强类型的实体定义。

LLBL Gen Pro 4.2 Lite主界面如下图所示:

Lite 版没有使用时间上的限制,限制一个项目只能创建8个实体。做实际的项目开发可能远远不够,一个实际的项目通常都有几十上百个表,但是做项目练习或是学习已经足够了。

说点题外话,7.20微软就正式发布Visual Studio 2015,同时也会提供全功能版的Visual Studio Comunitiy Edition,可用于非商业软件的开发。这样策略可以让技术和工具得到进步,使用免费版的客户也可以提出许多合理的有建设性的建议。国内的一些软件也提供了这样的策略,在推广自己软件的同时,免费版完全免费使用,包含基本的功能,同时维护一些高级别的功能用于付费用户。也有些极端的做的很不友好的软件:百度网盘的客户端百度云,在没有提供加速下载功能前,速度是很快的,推出了加速下载服务,没有付费用户的下载慢如蜗牛,平时2MB的下载速度一下子跌到300K左右,这让免费用户情何以堪。这有点类似企业邮箱,免费的邮箱用户支持着付费用户,如果不是这些免费用户在用,在推广,付费用户肯定会大面积逃离。同样的是网盘功能,企业的付费用户共享一个文件,免费用户去读取,后者因为速度原因体验性太糟糕,最终影响的还是付费用户的流失。

企业应用架构模式一书中提到二种组织领域逻辑的模式:事务脚本(Transaction Script)和领域模型(Domain Model)。前者就是我们通常做的封装SQL语句到类型定义文件中,逻辑的组织方式通过SQL语句的封装调用来实现,来看一个事务脚本(Transaction Script)的例子:

界面层,直接读取类获取数据:

DataTable table = Database.GetPendingDesignTask(Database.CONNNECTION_STRING_COMPANY, Database.UserId);
table.Columns.Add("SubmitDrawing", typeof(string));
table.Columns.Add("SubmitSubmited", typeof(string));
designTaskBindingSource.DataSource = table;
gridDesignTask.DataSource = designTaskBindingSource;

逻辑层 Database类定义如下方法:

public static DataTable GetPendingDesignTask(string connectionString, string designer)
{
          DataTable table=new DataTable("Query");
          string query = @"SELECT [Recnum],[RefNo] ,[EntryNo],[TaskNo] ,[ScheduleDate]
                        ,[ProjectNo] ,[ProjectName],[OrderNo],[ItemNo],[ContractNo]
                        ,[Designer],[Reviewer],[Closed],[ClosedBy] ,[ClosedDate]
                        ,[Confirmed] ,[ConfirmDate] ,[ConfirmBy] ,[Path]
                        ,[Drawing] ,[SubmitDate] ,[Submited] ,[Reviewed]
                        ,[ReviewDate] ,[ContractProduct] ,[CheckIn]
                        ,[CheckInDate] ,[CheckInBy],[LibraryFolderName]
                        ,[LibraryFullPath] ,[EcnPath],[EcnDrawing]
                        FROM  [PdmDesignTaskDetail]  WHERE Confirmed='Y' AND Submited='N' AND Designer='{0}' ";
          table=SqlHelper.ExecuteDataTable(connectionString, string.Format(query, designer));
          return table;
}

事务脚本中,逻辑的组织方式通过代码组合SQL语句调用来实现。

再来看领域模型(Domain Model):

界面层,只做数据绑定

protected override void BindControls(EntityBase2 entity)
{
        base.BindControls(entity);
        this.salesBindingSource.DataSource = entity;

}

逻辑层 过帐逻辑部分代码例子:

private void ProcessPaymentDetail(Guid sessionId, AccountsPayablePaymentDetailEntity accountsPayablePaymentDetail)
{
          IAccountsPayableInvoiceManager accountsPayableInvoiceMapager = ClientProxyFactory.CreateProxyInstance<IAccountsPayableInvoiceManager>();
          if (!accountsPayableInvoiceMapager.IsInoviceExist(sessionId, accountsPayablePaymentDetail.InvoCtrlNo))
              return;

AccountsPayableInvoiceEntity apInvoice = accountsPayableInvoiceMapager.GetAccountsPayableInvoice(sessionId, accountsPayablePaymentDetail.InvoCtrlNo, null);
          this.UpdateSettledInvoice(apInvoice, accountsPayablePaymentDetail);
          this.UpdateSettlementsLedger(sessionId, accountsPayablePaymentDetail);

accountsPayablePaymentDetail.Posted = false;
          accountsPayablePaymentDetail.SettledAmt = 0m;
          accountsPayablePaymentDetail.LogNo = 0m;
          accountsPayablePaymentDetail.InvRoundDiff = 0m;
          accountsPayablePaymentDetail.LastLogNo = apInvoice.LastLogNo;

accountsPayableInvoiceMapager.SaveAccountsPayableInvoice(sessionId, apInvoice);
}

逻辑的组织方式是面向对象的编程,对象的交互调用。

当经历过几年的面向对象的编程洗礼后,遇到事务脚本类型的代码态度甚至是不可容忍的。我列举对象关系映射的几点实际经验,供读者参考:

1  跟踪一个变量的的值来源或计算方法。这是管理软件常常遇到的一项问题,追踪一个字段的计算方法。对于事务脚本,需要借助于SQL Server Profiler这样的工具在跟踪值的变化,或是用字段名称来搜索相关的程序代码调用,如果是用领域模型,你常常只需要在计算的赋值方法处放一个断点,再启动调用器:

这幅图是简单的给TranCount属性设置了一个set断点,简单的动作包含了深刻的含义,调试状态下,所有给TranCount赋值的地方都会暂停以下以方便观察值的计算方法。

如果有安装Resharper插件,在变量名称上点击右键,选Find Usage,呈现如下的窗口:

有了这个功能,简单的情况下不必要调试源代码就可以知道变量的计算方法。这个方法在维护大型系统经常用到,也是面向对象编程良好可维护性的体现。

2 当字段值有发生改变时才产生SQL语句。事务脚本或是领域模式最终都是生成SQL语句发送到数据库引擎中执行。如果是事务脚本,直接写一个字段的更新语句,例子如下

public static void UpdatePendingDesignTaskForSubmitApproval(string connectionString, string refNo,decimal entryNo,string drawing)
       {
           string query = string.Format(" UPDATE PdmDesignTaskDetail SET Submited='Y',[Path]='{2}', [Drawing]='{2}',SubmitDate=GETDATE()  WHERE RefNo='{0}' AND EntryNo={1} ", refNo, entryNo, drawing);
           SqlHelper.ExecuteNonQuery(connectionString, query);
       }

这样的代码会随着参数个数不同而膨胀的非常糟糕。当我需要修改,增加SET部分的字段值更新,则会导致需要修改SQL语句和接口文件,维系起来相当麻烦。

对于领域模型,LLBL Gen Pro在生成UPDATE 更新语句时会检测字段值是否发生变化,若没有变化则不生成SQL SET部分的更新语句。

所以,无论界面上修改了几个控件,保存的代码永远是这样一句:

adapter.SaveEntity(InventoryMovement, true, false);

可维护性方面甩事务脚本几条街。

3 面向对象优点(封装,继承,多态)体现在基于对象关系映射的项目,给项目开发和维护带来了极大的便利。

LLBL Gen Pro的生成实体的特性:

提供一套验证框架:包含字段验证,实体验证,删除验证,保存验证,更新验证

验证类型的例子代码:

[Serializable]
    public partial class AccountValidator : ValidatorBase
    {
        // Add your own validation code between the two region markers below. You can also use a partial class and add your overrides in that partial class.
        // __LLBLGENPRO_USER_CODE_REGION_START ValidationCode
        public override void ValidateEntityBeforeDelete(IEntityCore involvedEntity)
        {
            base.ValidateEntityBeforeDelete(involvedEntity);

AccountEntity account = (AccountEntity)involvedEntity;
            RelationPredicateBucket filterBucket = new RelationPredicateBucket();
            filterBucket.PredicateExpression.Add(VoucherDetailFields.AcctNo == account.AcctNo);

IVoucherDetailManager voucherDetailManager = ClientProxyFactory.CreateProxyInstance<IVoucherDetailManager>();
            if (voucherDetailManager.IsVoucherDetailExist(Shared.CurrentUserSessionId, filterBucket))
                throw new EntityValidationException(account.AcctNo, "Cannot delete. Voucher entry for account exists");
        }

提供一套对象间关系的表达方法:对象之间的关联引用与主从关系很容易上手和处理,一切皆是对象。

主从表的查询关系写法例子,表示仓库单据下面的仓库进出明细,还有仓库进出明细下的批号和货格也同时引用到。

private IPrefetchPath2 DefaultPrefetchPath
       {
           get
           {
               IPrefetchPath2 prefetchPath = new PrefetchPath2((int)EntityType.InventoryMovementEntity);
               IPrefetchPathElement2 element = prefetchPath.Add(InventoryMovementEntity.PrefetchPathInventoryMovementDetails);
               element.SubPath.Add(InventoryMovementDetailEntity.PrefetchPathInventoryMovementBins);
               element = element.SubPath.Add(InventoryMovementDetailEntity.PrefetchPathInventoryMovementLots);
               element.SubPath.Add(InventoryMovementLotEntity.PrefetchPathInventoryMovementSerials);

return prefetchPath;
           }
       }

提供几套查询语法,方便数据查询。LLBL Gen Pro提供以下几种查询语法:

传统的写法,这种写法的通用性好,可直接用代码生成器生成。

InventoryMovementEntity inventoryMovement = new InventoryMovementEntity(refNo);
bool found = adapter.FetchEntity(inventoryMovement, prefetchPath, null, fieldList);

QuerySpec的写法:

query.OrderBy("FullName".Ascending());

LINQ 写法:

var trans = new Transaction(IsolationLevel.ReadCommitted, "SSTest");
var metaData = new LinqMetaData(trans);
var q = from c in metaData.Customers select c;

后两种写法很少用在实际开发中,经验不足。

总结LLBL Gen 开发框架提供的基础功能:

1  代码生成器(GUI或Console) ,当字段变化或是增减实体时,可重新生成实体定义。

2  验证框架,提供对象或对象的值的验证。

3  查询语法,可以面向对象的方式检索数据。

4  对象关系的表达。LLBL Gen Pro可以基于数据库的主从关系,生成对象之间的主从关联,方便操作数据。

一般的基于数据库表的实体代码生成器,无法实现或是灵活简单的实现后面3条,在代码开发速度和可维护性方面远远低于LLBL Gen Pro。

LLBL Gen Pro 4.2 Lite 免费的对象关系映射开发框架与工具的更多相关文章

  1. 接触LLBL Gen Pro 对象关系映射框架后 前途变的一片光明

    时间回到2010年,那时候还是熟悉代码生成+基础框架这种模式,基本的开发思路是通过代码生成器生成实体,再生成接口与实现类,最后拖拉控件,写界面数据绑定代码.基本上就是动软代码生成器给出的模式,或是微软 ...

  2. Enterprise Solution 3.1 企业应用开发框架 .NET ERP/CRM/MIS 开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    行业:基于数据库的制造行业管理软件,包含ERP.MRP.CRM.MIS.MES等企业管理软件 数据库平台:SQL Server 2005或以上 系统架构:C/S 开发技术 序号 领域 技术 1 数据库 ...

  3. 解析大型.NET ERP系统数据访问 对象关系映射框架LLBL Gen Pro

    LLBL Gen Pro是一个为.NET开发人员设计的的对象关系映射(ORM)框架,与NHibernate,Entity Framework等框架一样,通过实体与数据表的映射,实现关系数据库持久化. ...

  4. LLBL Gen Pro 5.0 企业应用开发入门

    Solutions Design 公司于2016年5月发布了LLBL Gen Pro 5.0,这个新版本的发布出乎于我的意料.我的猜想是从4.2升级到4.5,再升级5.x版本,主版本号的变更会给原有客 ...

  5. LLBL Gen Pro 5.0

    LLBL Gen Pro 5.0 企业应用开发入门 Solutions Design 公司于2016年5月发布了LLBL Gen Pro 5.0,这个新版本的发布出乎于我的意料.我的猜想是从4.2升级 ...

  6. 直接修改.NET程序集 LLBL Gen 2.x-4.x 许可授权方法研究

    做数据库开发,如果要用ORM,LLBL Gen是一款优秀的框架和工具,目前最新版本是4.0.同时也推出了Lite免费版本,与Visual Studio的Express版本一样, 免费,但是它仅仅只支持 ...

  7. LLBL Gen + Entity Framework 程序设计入门

    Entity Framework推出有好几年,除了微软的Visual Studio可以做实体框架开发外,第三方的开发工具如LLBL Gen, Devart Entity Developer也可以用来做 ...

  8. 最佳的 14 个免费的响应式 Web 设计测试工具

    一旦你决定要搭建一个网站就应该已经制定了设计标准.你认为下一步该做什么呢?测试!我使用“测试”这个词来检测你网站对不同屏幕和浏览器尺寸的响应情况.测试在响应式网页设计的过程中是很重要的一步.如果你明白 ...

  9. Oracle免费的便捷Web应用开发框架

    Oracle免费的便捷Web应用开发框架 APEX 总体来说,APEX是我见过最便捷最高效的开发框架,用起来比PHP还舒服.上手简单,学习成本极低,曾经有个做行政的小女生,在我指导下两天就可以开发出简 ...

随机推荐

  1. ubuntu上搭建review board代码评审站点

    Reviewboard是一个开源个人可以免费使用的代码评审框架,貌似现在有越来越多的公司也开始使用reviewboard作为公司的代码评审工具. 今天早上试了一下,搭建过程非常方便简单,按照网页提示即 ...

  2. Sqlite 管理工具收藏

    1.SQLite Administrator   http://download.orbmu2k.de/files/sqliteadmin.zip 2.SQLite2009Pro-v3.8.3.1 h ...

  3. 搜索栏css代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 找回忘记的Ubuntu用户名和密码

    找回忘记的Ubuntu用户名和密码 前端时间使用VMWare安装了个Ubuntn的虚拟机,但是烦于安装后显卡驱动的问题,看着操作界面就有点厌烦,就扔下了.今天打开虚拟机登陆的时候忘了密码,寻思着难道要 ...

  5. 【AspNetCore】【WebApi】扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat)

    扩展Webapi中的RouteConstraint中,让DateTime类型,支持时间格式化(DateTimeFormat) 一.背景 大家在使用WebApi时,会用到DateTime为参数,类似于这 ...

  6. 【腾讯Bugly干货分享】从0到1打造直播 App

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d42e7fd6ec467453bf58 作者:李智文 概要 分享内容: ...

  7. 《kali linux 渗透测试初级教程》免费下载

    Kali Linux系列教程是在51cto上售卖的入门教程,售价100元.每天都有很多网友找我要全部教程,也有人偷偷的录制了教程.索性公开出来,如果您觉得还可以的话,希望可以选择发个小红包或者转发 获 ...

  8. Wix 安装部署教程(十) --来,用WPF做个漂亮的安装界面

    在上一篇中曾留下两个问题,.Net捆绑安装不触发以及路径选择的问题现在都已经解决,这段时间花的最多的地方还是WPF调样式上面,奈何WPF功力不够,暂时还是没有达到自己想要的效果.另外ViewModel ...

  9. C# Lambda表达式详解,及Lambda表达式树的创建

    最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...

  10. SQL语句中,Conversion failed when converting datetime from character string.错误的解决办法

    在项目开发过程中,我们经常要做一些以时间为条件的查询,比如查询指定时间范围内的历史记录,然而这些时间都是从UI传递过来的参数,所以我们写的sql语句就必须用到字符串拼接.当然,在C#中写SQL语句还好 ...