ado.net entity framework使用odp.net(ODAC for .net)连接oracle11g体验
标签
odp.net (ODAC for .net)
ado.net entity framework database first
winform
内容简介
小项目ado.net entity framework使用odp.net连接oracle11g体验分享。没啥技术含量,高手请绕行!
1、架构,没分层小程序而已,没必要那么麻烦。
2、edmx模型(使用向导从数据库生成)
3、程序界面截图
4、主要代码和使用到EF、odp.net的使用体验。
(1)扩展向导生成的Context对象。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DnaSecurityCodeApp { public partial class SecurityCodeEntities { /// <summary> /// 获取oracle服务器当前系统时间,select sysdate from dual; /// </summary> /// <param name="sqlCmd"></param> /// <returns></returns> public DateTime GetDbServerDateTime() { DateTime result = DateTime.Now; try { result = this.ExecuteStoreQuery<DateTime>("select sysdate from dual", new object[] { }).FirstOrDefault(); } catch (Exception ex) { throw ex; } return result; } /// <summary> /// 执行指定脚本,返回受影响的行数 /// </summary> /// <param name="sqlTxt"></param> /// <returns></returns> public int ExecuteSql(string sqlTxt) { try { return this.ExecuteStoreCommand(sqlTxt, new object[] { }); } catch (Exception ex) { return -1; throw ex; } } /// <summary> /// 返回查询结果,只能支持查询一列数据,且需要明确指定返回值的类型 /// </summary> /// <param name="sqlCmdTxt"></param> /// <returns></returns> public string GetSingleValue<T>(string sqlCmdTxt) { try { var obj = this.ExecuteStoreQuery<T>(sqlCmdTxt, new object[]{}); return obj.FirstOrDefault().ToString(); } catch (Exception ex) { return string.Empty; throw ex; } } } }
写这个类主要是使用oracle特定的sql语法获取oracle服务器信息,比如sysdate、数据库版本、字符集、序列的下一个值等。
ef使用odp.net的连接字符串:
<?xml version="1.0" encoding="utf-8"?> <configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" /> </startup> <connectionStrings> <add name="SecurityCodeEntities" connectionString="metadata=res://*/SecurityCodeDb.csdl|res://*/SecurityCodeDb.ssdl|res://*/SecurityCodeDb.msl;provider=Oracle.DataAccess.Client;provider connection string="DATA SOURCE=jp2012;PASSWORD=123#dba;PERSIST SECURITY INFO=True;USER ID=JP2012"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration>
provider=Oracle.DataAccess.Client,ef会自动使用odp.net对应版本的比如Oracle.DataAccess.dll等一般为了部署程序时应该将那几个必须的dll一并打包放到主程序同一目录下。关于这个请参看园子里Oracle免Client打包的文章,一时也说不清楚。我的程序小部署时就手工装了200M多的ODAC了事。
EF使用场景(这里只有"增、改、查"没有"删"):
1)查:
string sqlSecondTxt = string.Format("SELECT R.END_ID FROM SECURITYCODE_REGION R " + "WHERE TO_CHAR(R.PRODUCTDATE,'YYYY-MM-DD') = (SELECT TO_CHAR(MAX(V.PRODUCTDATE),'YYYY-MM-DD') FROM SECURITYCODE_REGION V WHERE V.PRDFACTORYCODE = '{0}' AND V.PRDLINENO='{1}') AND " + "R.PRDFACTORYCODE = '{2}' AND R.PRDLINENO='{3}'", txtFacNo.Text.Trim(), txtPrdLineCode.Text.Trim(), txtFacNo.Text.Trim(), txtPrdLineCode.Text.Trim()); string result = oraDb.GetSingleValue<decimal>(sqlSecondTxt);
2)又查又改:
var regEntity = oraDb.SECURITYCODE_REGION.Where("it.END_ID = @end_id and it.PRDFACTORYCODE =@facNo and it.PRDLINENO = @prdLine", new ObjectParameter[]{ new ObjectParameter("end_id",beginIdentityNo), new ObjectParameter("facNo",txtFacNo.Text.Trim()), new ObjectParameter("prdLine",txtPrdLineCode.Text.Trim()) }).FirstOrDefault(); if (regEntity != null) { regEntity.END_ID = beginIdentityNo + codeCountNum; regEntity.ROWVERSIONFLAG = oraDb.GetDbServerDateTime(); oraDb.SaveChanges(); }
3)增:
#region 新增记录,起始截至先看前一次的,如果没有默认从0开始 SECURITYCODE_REGION region = new SECURITYCODE_REGION(); var seq = oraDb.GetSingleValue<decimal>("select product_reg_seq.nextval from dual"); region.IDENTITYNO = long.Parse(seq); region.PRDFACTORYCODE = txtFacNo.Text.Trim(); region.PRDLINENO = txtPrdLineCode.Text.Trim(); region.PRODUCTNO = int.Parse(txtProductNo.Text.Trim()); region.PRODUCTNAME = txtProductName.Text.Trim(); region.PRODUCTDATE = DateTime.Parse(dtProduct.Value.ToShortDateString() + " 00:00:00"); region.ROWVERSIONFLAG = DateTime.Now; region.BATCHNO = txtBatchNo.Text.Trim(); region.BEGIN_ID = beginIdentityNo; region.END_ID = beginIdentityNo + codeCountNum; oraDb.SECURITYCODE_REGION.AddObject(region); oraDb.SaveChanges(); #endregion
4)其他查询:
/// <summary> /// 按产品代码进行增量查询(模糊查询) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void txtPrdCode_TextChanged(object sender, EventArgs e) { if ((txtPrdCode.Text.Trim().Length > 0) && txtPrdCode.Focused) { using (SecurityCodeEntities db = new SecurityCodeEntities()) { var list = db.ExecuteStoreQuery<SC_JP_PRODUCTINFO>(string.Format("select * from SC_JP_PRODUCTINFO t where t.product_code like '{0}%'", txtPrdCode.Text.Trim()), new object[] { }).OrderBy(p => p.PRODUCT_CODE).Take(100); gridSource.DataSource = list; } } }
这里有个插曲,EF使用like关键字,好像看msdn里面是可以的,可能是EF版本缘故吧,"PRODUCT_CODE"是number(6)整数类型,在linq to object的时候不能使用Contains()来代替like "%value%"这种。实在没辙了,PLSQL DEVELOP里面运行整数字段也是可以where like "value%"实现增量查询的啊。无奈使用上面的办法成功了。
其他类型的比如varchar2的字段是可以的:
using (SecurityCodeEntities db = new SecurityCodeEntities()) { string selVal = cbxpp.SelectedItem.ToString(); gridSource.DataSource = db.SC_JP_PRODUCTINFO. Where(p => p.PRD_BRAND.Contains(selVal)).ToList(); dataGridView.Focus(); }
另外绑定datagridview的数据源使用直接绑定项目对象(EF模型里的实体)的方式:
总结:
1)用下来EF使用ODP.NET效率还挺高,小项目使用database first方式很方便。
2)快速啊。分层啊、架构啊神马的都是浮云,小项目三下两下搞定好下班!
希望没有浪费您宝贵的时间。我也不知道写啥,有用您就看看,可别骂我啊!
"作者:" 数据酷软件工作室
"出处:" http://datacool.cnblogs.com
"专注于CMS(综合赋码系统),MES,WCS(智能仓储设备控制系统),WMS,商超,桑拿、餐饮、客房、足浴等行业收银系统的开发,15年+从业经验。因为专业,所以出色。"
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++