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)快速啊。分层啊、架构啊神马的都是浮云,小项目三下两下搞定好下班!

希望没有浪费您宝贵的时间。我也不知道写啥,有用您就看看,可别骂我啊!

 

posted @ 2012-08-01 13:28  数据酷软件  阅读(3356)  评论(4编辑  收藏  举报