none
如何动态(runtime)构建数据层 RRS feed

  • 问题

  • 在考虑一个类似数据管理的n-tier系统,UI层使用Silverlight等RIA。需求是用户可以在运行时根据需求创建所需的各类数据实体类型或表结构,如Products、Orders等,类型间/表间的关系可能较复杂。然后实现增删改查操作。

    这种情况下,使用Entity Framework等框架是否合适?怎么感觉这些orm框架对于运行时动态构建或更新持久层结构支持地不怎么好?使用这些框架,在更改实体层结构后,是否一定需要重新编译项目?

    针对上述需求有否好的建议,感谢!

    2010年9月6日 9:52

答案

  • 参考一下这篇文章,

    在Silverlight端运行时发射生成实体类,来包裹服务返回的datatable数据

    http://blog.bodurov.com/blog/Post.aspx?postID=27

     


    Mog Liang
    • 已标记为答案 Evan Tan 2010年9月10日 9:37
    2010年9月9日 1:54
  • C#运行时编译请参见CodeDOM 类。 产生实体类跟数据库里的数据没关系,只跟表结构有关。只是如果用户自定义的表结构变了的话,会影响已有数据(删除了某个字段)

    动态编译好实体类后只能用反射的方式去用它,系统复杂度会变得很高了。

    public static bool CompileCSharpCode(String sourceFile, 
      String exeFile)
    {
      CSharpCodeProvider provider = new CSharpCodeProvider();
    
      // Build the parameters for source compilation.
      CompilerParameters cp = new CompilerParameters();
    
      // Add an assembly reference.
      cp.ReferencedAssemblies.Add( "System.dll" );
    
      // Generate an executable instead of 
      // a class library.
      cp.GenerateExecutable = true;
    
      // Set the assembly file name to generate.
      cp.OutputAssembly = exeFile;
    
      // Save the assembly as a physical file.
      cp.GenerateInMemory = false;
     
      // Invoke compilation.
      CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);
    
      if(cr.Errors.Count > 0)
      {
        // Display compilation errors.
        Console.WriteLine("Errors building {0} into {1}", 
          sourceFile, cr.PathToAssembly);
        foreach(CompilerError ce in cr.Errors)
        {
          Console.WriteLine(" {0}", ce.ToString());
          Console.WriteLine();
        }
      }
      else
      {
        Console.WriteLine("Source {0} built into {1} successfully.",
          sourceFile, cr.PathToAssembly);
      }
         
      // Return the results of compilation.
      if (cr.Errors.Count > 0)
      {
        return false;
      }
      else 
      {
        return true;
      }
    }
    • 已标记为答案 Evan Tan 2010年9月10日 9:37
    2010年9月9日 7:23

全部回复

  • 就我个人认为,ORM不支持运行时实体结构更新。你若需要动态更新的话,可以尝试通过WCF向Silverlight暴露执行Sql的contract。


    Mog Liang
    2010年9月8日 7:05
  • 我想应该区分哪些是用户创建的表,哪些是你的系统需要使用的表。

    对于用户通过系统创建的表,是不太可能做ORM的。因为结构都不固定,怎么去mapping呢。即便能用动态编译手法做过实体出来,也不是很推荐,那样还不如SQL语句来的更简单方便,因为实体本身都不是固定类型的。

    系统使用的固定表部分倒是可以用ORM方式。

    2010年9月8日 9:33
  • 感谢斑竹和南帝哈。

    考虑用ORM的初衷是两个,一个是确实想利用实体类,因为像WPF、SL的很多控件都是binding到类上的,直接操作表字段的话感觉比较难搞。。。二个是想用orm处理实体/表之间的复杂关联关系。。。 如果直接操作sql的话,二位有没思路指点一下?

    另外,如果一定用EF的话,想运行时编译生成实体结构,然后把类放到某个库里让前端的SL编译调用之类的,怎么来操作呢?后台调用edmgen.exe然后msbuild么? ef每次重新编译的时候是否数据库里的数据就都丢失了

    2010年9月8日 12:08
  • 参考一下这篇文章,

    在Silverlight端运行时发射生成实体类,来包裹服务返回的datatable数据

    http://blog.bodurov.com/blog/Post.aspx?postID=27

     


    Mog Liang
    • 已标记为答案 Evan Tan 2010年9月10日 9:37
    2010年9月9日 1:54
  • C#运行时编译请参见CodeDOM 类。 产生实体类跟数据库里的数据没关系,只跟表结构有关。只是如果用户自定义的表结构变了的话,会影响已有数据(删除了某个字段)

    动态编译好实体类后只能用反射的方式去用它,系统复杂度会变得很高了。

    public static bool CompileCSharpCode(String sourceFile, 
      String exeFile)
    {
      CSharpCodeProvider provider = new CSharpCodeProvider();
    
      // Build the parameters for source compilation.
      CompilerParameters cp = new CompilerParameters();
    
      // Add an assembly reference.
      cp.ReferencedAssemblies.Add( "System.dll" );
    
      // Generate an executable instead of 
      // a class library.
      cp.GenerateExecutable = true;
    
      // Set the assembly file name to generate.
      cp.OutputAssembly = exeFile;
    
      // Save the assembly as a physical file.
      cp.GenerateInMemory = false;
     
      // Invoke compilation.
      CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);
    
      if(cr.Errors.Count > 0)
      {
        // Display compilation errors.
        Console.WriteLine("Errors building {0} into {1}", 
          sourceFile, cr.PathToAssembly);
        foreach(CompilerError ce in cr.Errors)
        {
          Console.WriteLine(" {0}", ce.ToString());
          Console.WriteLine();
        }
      }
      else
      {
        Console.WriteLine("Source {0} built into {1} successfully.",
          sourceFile, cr.PathToAssembly);
      }
         
      // Return the results of compilation.
      if (cr.Errors.Count > 0)
      {
        return false;
      }
      else 
      {
        return true;
      }
    }
    • 已标记为答案 Evan Tan 2010年9月10日 9:37
    2010年9月9日 7:23