標簽
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)快速啊。分層啊、架構啊神馬的都是浮雲,小項目三下兩下搞定好下班!
希望沒有浪費您寶貴的時間。我也不知道寫啥,有用您就看看,可別罵我啊!
