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)快速啊。分層啊、架構啊神馬的都是浮雲,小項目三下兩下搞定好下班!

希望沒有浪費您寶貴的時間。我也不知道寫啥,有用您就看看,可別罵我啊!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM