zoukankan      html  css  js  c++  java
  • 在.NET开发面向Oracle数据库的应用程序

    其实这个不是一个什么新的话题。但是之前在多次项目中,总是遇到大家针对Oracle数据库的访问时,会有各种各样的问题,最基本的就是要在客户端安装各种client,版本不一样的话还有各种问题。

    静下心来看看,其实也没有那么难。我这里总结一下,如何在.NET应用程序中,简单优雅地使用Oracle数据库。

    第一个原则:不要依赖

    最好的情况就是,程序自己就可以完成数据访问,不需要额外地安装所谓的Oracle Client,那是一个很麻烦而且痛苦的事情。

    我们首先看看,如果不装任何东西,是否可以实现Oracle数据库访问?

    其实,.NET本身是自带了针对Oracle数据库访问的组件的,就是下面这个System.Data.OracleClient

    image

    我们的代码如下(这是最原始的ADO.NET代码,只是做演示)

    using System;
    using System.Data.OracleClient;

    namespace ConsoleApplication
    {
        class Program
        {
            static void Main(string[] args)
            {
                var connectionString = "user id=system;password=password;data source=192.168.56.101:1521/orcl";

                using (var connection = new OracleConnection(connectionString))
                {
                    var cmd = connection.CreateCommand();
                    cmd.CommandText = "select * from sys.dba_all_tables";
                    connection.Open();
                    var reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine(reader.GetString(0));

                    }

                    reader.Close();
                    connection.Close();

                }
               
            }
        }
    }

    看起来应该是没有问题的,运行起来却会报错

    Additional information: System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.

    image

    这里的提示就是说,需要有Oracle Client。

    这不是我们希望看到的结果。实际上原理上说,我们这么理解吧,可能是这个组件只是一个wrapper,它实际去操作数据库,还需要通过Oracle Client才能实现。

    使用Oracle提供的组件

    更好的建议就是,使用Oracle 官方提供的托管代码组件。Oracle.ManagedDataAccess.dll

    image

    image

    只要添加了这个Nuget Package,代码几乎不需要任何改动,直接就可以复用。

    using System;
    using Oracle.ManagedDataAccess.Client;

    namespace ConsoleApplication
    {
        class Program
        {
            static void Main(string[] args)
            {
                var connectionString = "user id=system;password=password;data source=192.168.56.101:1521/orcl";

                using (var connection = new OracleConnection(connectionString))
                {
                    var cmd = connection.CreateCommand();
                    cmd.CommandText = "select * from sys.dba_all_tables";
                    connection.Open();
                    var reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        Console.WriteLine(reader.GetString(0));

                    }

                    reader.Close();
                    connection.Close();

                }
               
            }
        }
    }

    当然比较理想的情况是将连接字符串之类的,可以放在配置文件中去。这个很简单,这里就不说明了。

    结合Entity Framework使用

    Entity Framework 出来已经好多年了,几乎成了所有.NET应用程序中的标配(不管有没有用到)。现在的最新版本应该是 6.1.3 .同时,需要注意的是,以后会有一个所谓的Entity Framework Core ,而且开源了 https://github.com/aspnet/EntityFramework

    回到正题,之前的代码写法其实还是比较原始的,那么如何结合Entity Framework进行Oracle数据库方面的编程呢?

    首先,安装下面的这个组件:Oracle.ManagedDataAccess.EntityFramework

    image

    然后,可以使用Code first的方式编写如下代码

    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity;

    namespace ConsoleApplication
    {
        public class OracleContext : DbContext
        {
            public OracleContext() : base("OracleDbContext")
            {

            }

            public DbSet<Employee> Employees { get; set; }

        }

        [Table("EMPLOYEES", Schema = "SYSTEM")]
        public class Employee
        {
            [Key()]
            [Column("EMPLOYEEID")]
            public int EmployeeID { get; set; }

            [Column("FIRSTNAME")]
            public string FirstName { get; set; }
            [Column("LASTNAME")]
            public string LastName { get; set; }
        }
    }

    这里的代码没有什么出奇的。配置文件需要有如下的设置(一般在添加Oracle.ManagedDataAccess.EntityFramework 这个组件的时候,会自动修改配置文件)

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <section name="oracle.manageddataaccess.client" type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
      </startup>
      <oracle.manageddataaccess.client>
        <version number="*">
          <dataSources>
            <dataSource alias="oracle" descriptor="(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.101)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) " />
                 </dataSources>
        </version>
      </oracle.manageddataaccess.client>
      <connectionStrings>
        <add name="OracleDbContext" connectionString="user id=system;password=password;data source=oracle" providerName="Oracle.ManagedDataAccess.Client" />
      </connectionStrings>
      <system.data>
        <DbProviderFactories>
          <remove invariant="Oracle.ManagedDataAccess.Client" />
          <add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver" type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
        </DbProviderFactories>
      </system.data>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <publisherPolicy apply="no" />
            <assemblyIdentity name="Oracle.ManagedDataAccess" publicKeyToken="89b483f429c47342" culture="neutral" />
            <bindingRedirect oldVersion="4.121.0.0 - 4.65535.65535.65535" newVersion="4.121.2.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
      <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
          <parameters>
            <parameter value="v13.0" />
          </parameters>
        </defaultConnectionFactory>
        <providers>
          <provider invariantName="Oracle.ManagedDataAccess.Client" type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
      </entityFramework>
    </configuration>

    后台数据库的表格设计也是很简单。

    image

    需要注意的是,经过实验,我发现目前这个Entity Framework要求所操作的表必须要有主键,而且主键必须是一个identity column(即自己绑定一个序列,实现自动增长),否则会报错

    实际上后台会通过一个触发器来实现这个功能

    create or replace TRIGGER EMPLOYEES_TRG
    BEFORE INSERT ON EMPLOYEES
    FOR EACH ROW
    BEGIN
      <<COLUMN_SEQUENCES>>
      BEGIN
        IF INSERTING AND :NEW.EMPLOYEEID IS NULL THEN
          SELECT EMPLOYEES_SEQ.NEXTVAL INTO :NEW.EMPLOYEEID FROM SYS.DUAL;
        END IF;
      END COLUMN_SEQUENCES;
    END;

    接下来在前端程序中就简单多了,下面是一个代码片段

    var ctx = new OracleContext();

    ctx.Employees.Add(new Employee() {FirstName = "ares", LastName = "chen" });
    ctx.SaveChanges();

    var query = ctx.Employees.ToArray();
    foreach (var item in query)
    {
        Console.WriteLine(item);
    }

    需要注意的是,如果需要使用Entity Frmaework的Database first或Model first的功能,还是需要安装Oracle Client,或者准确地说应该是ODAC组件

    http://www.oracle.com/technetwork/developer-tools/visual-studio/downloads/index.html

  • 相关阅读:
    ADO 缓存更新
    DBNavigator中把insert变为append
    JQuery 选择器
    VS2013默认打开HTML文件没有设计视图
    windows 关机 重启 命令
    java如何计算两个日期之间相差多少天?
    java的list集合操作List<T>转化List<Long>
    ExcelUtil工具类
    oracle的START WITH CONNECT BY PRIOR用法
    oracle的with as用法
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/5415442.html
Copyright © 2011-2022 走看看