简体   繁体   中英

With ODP.NET, Create C# class/struct from Column Info of an Oracle DB's Table

Is there an established way/tool to automatically create generate C# class/struct containing the variables according to the columns of an Oracle DB's Table?

I currently am using ODP.Net to handle a number of Tables from Oracle DB. To ease me to handle the Database Table, I create a unique C# class for each of the Table which I read which store an info of the given DB's row

Currently, I am making each of the class manually. But I realize as the number of tables become more, my way gets more tedious.

Anyone encounter the same problem, having a good tool to ease the tasks?

In the general sense you're talking about converting the schema/metadata of the database to a different form. Most RDBMS expose this data as tables. For example this is a query I used to use to get all of the column data, clean it (like removing underscores), and transform it to .net types and statements:

with metadata as
(
        select 
          utc.table_name, 
          utc.column_name, 
          replace(initcap(replace( lower(utc.column_name) ,'_',' ')),' ','') as column_name_clean,
          initcap(replace( lower(utc.column_name) ,'_',' ')) as column_name_space,
          rtrim(substr(utc.column_name,1,26),'_') as column_name_26,
         case utc.data_type
            when 'DATE' then 'DateTime'
            when 'VARCHAR2' then 'String'
            when 'CLOB' then 'String'
            when 'NUMBER' then 
              case when utc.data_scale=0 then 
                case 
                  when utc.data_precision = 19 then 'Int64'
                  when utc.data_precision = 9 then 'Int32'
                  when utc.data_precision = 4 then 'Int16'
                  when utc.data_precision = 1 then 'Boolean'
                  else 'Int'|| utc.data_precision  end
              else 'Decimal' end
            when 'CHAR' then 
              case when utc.data_length = 1 then 'Char'
              else 'String' end
            else '' end as clr_data_type,
         case utc.data_type
            when 'DATE' then 'DateTime'
            when 'VARCHAR2' then 'Text'
            when 'CLOB' then 'MultilineText'
            when 'CHAR' then 'Text'
            else '' end as mvc_data_type, 
         case utc.data_type
            when 'DATE' then 'Date'
            when 'TIMESTAMP' then 'TimeStamp'
            when 'VARCHAR2' then 'Varchar2'
            when 'CLOB' then 'Clob'
            when 'NUMBER' then 
              case when utc.data_scale=0 then 
                case 
                  when utc.data_precision = 19 then 'Int64'
                  when utc.data_precision = 9 then 'Int32'
                  when utc.data_precision = 4 then 'Int16'
                  when utc.data_precision = 1 then 'Decimal-Boolean'
                  else 'Int'|| utc.data_precision  end
                else 'Decimal' end

            when 'CHAR' then 'Char'
            else '' end as odp_data_type, 
          utc.Data_Type as native_data_type,
         case when utc.data_type = 'VARCHAR2' or utc.data_type='CHAR' then Data_Length
            else null end as mvc_data_range, 
          utc.data_length,
          utc.data_precision,
          utc.data_scale,
          utc.nullable,
            case 
              when utc.data_scale > 0 then 
                '^\d{' || (nvl(utc.data_precision,1)-nvl(utc.data_scale,0)) || '}(\.\d{' || nvl(utc.data_scale,0) || '})?$'
              else '' end as validation_reg_ex,
          'n.' || trim(rpad(' ', nvl(utc.data_scale,0), 'd')) as validation_format,
          case utc.data_type
            when 'NUMBER' then
              case when utc.data_scale=0 then utc.data_precision
              else utc.data_precision + 1 end -- +1 for the decimal
            else
              utc.data_length end as max_string_length,
          case ac.constraint_type when 'P' then 'Y' else 'N' end as PRIMARY_KEY,
          ac.constraint_type
        from user_tab_columns utc
        left join all_cons_columns acc
          join all_constraints ac on ac.constraint_name = acc.constraint_name and ac.owner = acc.owner and ac.constraint_type='P'
          on utc.column_name=acc.column_name and utc.table_name=acc.table_name
        where utc.table_name not like 'BIN%'
        order by utc.table_name, utc.column_id
)
select 'public ' || clr_data_type || ' ' || column_name_clean || ' {get; set;}' as ClassProperty, m.*
from metadata m;

You'll note the first column, concatenates some of these fields together to form class properties:

SQL开发人员片段

In the past, I've added columns to generate everything from OracleCommand parameters, to inputs for the web. You can then take that farther with some sort of templating mechanism to generate whole classes, including data access methods, etc. T4 is an option but I used CodeSmith's Generator product.

While object-relational mappers like Entities or NHibernate, do a lot of this generation too, I don't appreciate their other purpose, which is to abstract the actual movement of data from database to middle tiers - the query languages they use are just too weak/convoluted to me. I prefer to stick with sql itself and maybe a micro-orm like dapper - of course i use the same techniques above to generate the sql for CRUD operations as well :).

Microsoft introduced Code Generation and T4 Text Templates which can be used to generate text output using some control logic. This article describes a way how to automate code generation from DB. T4 is a part of Visual Studio so there is no need to install additional software. To accomplish the task you need to write T4 text template which is

a mixture of text blocks and control logic that can generate a text file. The control logic is written as fragments of program code in Visual C# or Visual Basic.

You could also adapt an approach described in this article where it's shown how to create classes from the Datatable object. Basically you can use the System.CodeDom namespace to create a class containing the properties you need. In order to solve the problem, you need to complete the following steps:

  1. Declare a class using the CodeTypeDeclaration class.
  2. Create properties ( CodeMemberField ) for each column create a property and add it into the class.
  3. Create a namespace ( CodeNamespace ) and add the class into it.
  4. Generate a .cs file using the CSharpCodeProvider class.

I think that the first approach (use T4) is more effective and understandable. For example, let's imagine that you have the same method for all classes. You can simply add this method to a T4 file and it's clear what this method is doing. The second approach requires more code to define the method.

UDPATE

NHibernate Mapping Generator allows to generate the domain code from DB. You can simply copy these generated classes (from the Domain Code tab) and change them.

If you simply need to generate properties for your class then you could adapt adapt for Oracle the SQL script described here .

实体框架可与ODP.NET协同工作,并且对您有帮助,甚至更多。...是否有特定原因导致您不使用任何可用的ER映射器?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM