Какие подводные камни ожидать от генерации классов из таблиц базы данных с использованием файлов Reflection.Emit и xsd?

Я играю с генерацией классов (один класс для таблицы - наследование и т. Д., Пока не рассматриваются ...). Поэтому я бесстыдно скопировал здесь Reflection .Emit code. Переработал его, чтобы он создавался для каждой таблицы в данной базе данных, и создал файлы с помощью следующего пакетного вызова в папке bin проекта: for / f "tokens = *" %% i in ('dir * .xsd / b') do " C: \ Program Files \ Microsoft SDKs \ Windows \ v6.0A \ bin \ xsd.exe "-c -l: c # -n: BusinessObjects% i

Все идет нормально. Идея состоит в том, что каждый раз, когда приходит новая версия db, чтобы регенерировать классы и копировать их в «настоящий проект» (мне не нужна генерация во время выполнения), а также хотелось бы пользоваться Intellisense. Какие подводные камни, трудности и проблемы могут возникнуть из-за такого подхода, какие лучшие предложения по этим слабо описанным требованиям ?!

Вот код генерации консольного приложения, создающего сборки:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using log4net;
    using log4net.Config;
    using System.Data;
    using System.Data.SqlClient;
    using System.Threading;
    using System.Reflection;
    using System.Reflection.Emit;

    namespace GenerateAssemblies
    {

      class Program
      {

        private static readonly ILog logger =
             LogManager.GetLogger ( typeof ( Program ) );


        static void Main ( string[] args )
        {
          DOMConfigurator.Configure();  //tis configures the logger 
          logger.Debug ( "APP START" );

          DataTable dtTables = Program.GetTablesFromDb ( "POC" ) ;
          foreach (DataRow dr in dtTables.Rows)
          {
            string strTableName = dr[0].ToString () ;
            CodeEmitGeneratingAssemblies.DllGenerator.WriteXmlAndTxtFileOutOfDataTableByName (  strTableName);
            CodeEmitGeneratingAssemblies.DllGenerator.CreateAssembly ( strTableName );
          }


          Console.WriteLine ( " Should have now all the dll's " );
          Console.ReadLine ();
        } //eof method 



        static DataTable GetTablesFromDb ( string strDbName )
        {


          DataTable dt = new DataTable ( "tables" );

          string connectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=" + strDbName + ";Data Source=ysg";

          using (SqlConnection connection = new SqlConnection ( connectionString ))
          {
            SqlCommand command = connection.CreateCommand ();

            command.CommandText = string.Format ( "SELECT name from sys.tables" );

            connection.Open ();
            dt.Load ( command.ExecuteReader ( CommandBehavior.CloseConnection ) );
          }
          return dt;
        } //eof method 


      } //eof class 


    namespace CodeEmitGeneratingAssemblies
    {
      public class DllGenerator
      {
        private static readonly ILog logger =
             LogManager.GetLogger ( typeof ( DllGenerator ) );




        public static void WriteXmlAndTxtFileOutOfDataTableByName (string strDataTableName)
        {
          DOMConfigurator.Configure ();  //tis configures the logger 
          DataTable tableData = new DataTable ( strDataTableName );

          string connectionString = "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=POC;Data Source=ysg";

          using (SqlConnection connection = new SqlConnection ( connectionString ))
          {
            SqlCommand command = connection.CreateCommand ();

            command.CommandText = string.Format ( "SELECT * FROM [" + strDataTableName + "]");
            logger.Debug ( "command.CommandText is " + command.CommandText );
            connection.Open ();
            tableData.Load ( command.ExecuteReader ( CommandBehavior.CloseConnection ) );
          }

          tableData.WriteXml ( strDataTableName + ".xml" );
          tableData.WriteXmlSchema ( strDataTableName + ".xsd" );
        } //eof method 


        public static void CreateAssembly ( string strDataTableName )
        {
          AppDomain currentDomain = Thread.GetDomain ();

          AssemblyName myAssemblyName = new AssemblyName ( );
          myAssemblyName.Name = strDataTableName;

          AssemblyBuilder builder = currentDomain.DefineDynamicAssembly (
                              myAssemblyName,
                              AssemblyBuilderAccess.RunAndSave );

          builder.AddResourceFile ( "TableXml", strDataTableName + ".xml" );
          builder.AddResourceFile ( "TableXsd", strDataTableName + ".xsd" );

          builder.Save ( strDataTableName + ".dll" );
        }

      } //eof class 
    } //eof namespace 

    } //eof namespace 

person Yordan Georgiev    schedule 06.05.2009    source источник


Ответы (2)


Вы получаете все проблемы, связанные с использованием (реляционной) разработки oo, основанной на базе данных:

  • не хватает абстракции, наследования и построения ADT;
  • занятия со слишком большим количеством обязанностей;
  • поведение в неположенных местах;
  • нет удобного способа обработки временных аспектов.

Я предпочитаю работать наоборот. От модели oo к базе данных

[править] Вы можете попробовать заставить работать гибридную модель. Переход от БД к объектно-ориентированному объекту для одной части приложения и наоборот для другой части. Это позволяет медленно проводить рефакторинг и переходить на OO-> DB.

person Stephan Eggermont    schedule 06.05.2009
comment
Я согласен с вами ... Моя проблема в том, что на самом деле база данных уже существует, поэтому мне придется принять ее .. - person Yordan Georgiev; 07.05.2009

Да ... один лайнер с SubSonic:

sonic generate /override /server HOMIE /db BlogEngine /userid OMMITED /password OMMITED /out C:\code\out /generatedNamespace BlogEngine.Core.Providers.SubSonic /stripTableText be_
person Yordan Georgiev    schedule 28.05.2009