2012-02-05 8 views
5

私は遊んでいますが、それが実行可能かどうか、または多くの使用があるかどうかはわかりません。Roslynを使用してEF CodeFirst DbContextを作成する

私はRoslyn CTPを使用して非常に基本的なEFコードファーストデータベースを生成しようとしています。実行すると

var scriptEngine = new ScriptEngine(new[] { "System", "System.Core", typeof(DbContext).Assembly.Location }); 
var session = Roslyn.Scripting.Session.Create(); 

var t = scriptEngine.CompileSubmission<DbContext>(@" 
    using System.Data.Entity;   
    public class Car { 
    public int Id {get; set;} 
    public string Name {get; set; } 
    } 

    public class Context : DbContext { 
    public DbSet<Car> Cars {get; set; } 
    } 

    new Context(); 
", session); 

t.Execute(); 

私は次の例外

例外を取得:

コード

型 '服従#0 +カーは' マップされていませんでした。 IgnoreメソッドまたはNotMappedAttributeデータ注釈を使用して、型が明示的に除外されていないことを確認します。型がクラスとして定義されていて、プリミティブ、ネストまたはジェネリックではなく、EntityObjectから継承していないことを確認してください。

考えられる問題のリストを調べると、私はRoslynがコードジェネレーションの一部としてネストされたクラスを作っていると推測しています。そうでなければ、 "新しいContext();"コールはある種のクラス/メソッドにラップする必要があります。私は上記を確認するアセンブリを発行することができますが、それを正しく書く方法の手掛かりはないでしょう。

私もSyntax.ClassDeclarationのルートをたどりましたが、1つのプロパティを持つクラスを作成し、そのクラスをインスタンス化する明白な方法がないだけで、数百行のコードで終了しました。

質問

(例えば、別のクラスにネストされていない)公にアクセス可能であるロザリンクラスを作成する簡単な方法はありますか?

答えて

5

あなたのソースコードに基づいて、あなたのタイプが含まれている実際のDLLライブラリを作成し、そのスクリプトから使用するロスリンを使用することができますスクリプトにEFのフルパスを渡して、若干の修正を必要

var classCode = @" 
using System.Data.Entity; 

public class Car { 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class Context : DbContext { 
    public DbSet<Car> Cars { get; set; } 
}"; 

var syntaxTree = SyntaxTree.ParseCompilationUnit(classCode); 

var compilation = Compilation.Create(
    "car", 
    new CompilationOptions(assemblyKind: AssemblyKind.DynamicallyLinkedLibrary)) 
    .AddReferences(
     new AssemblyFileReference(typeof(object).Assembly.Location), // mscorlib 
     new AssemblyFileReference(typeof(Uri).Assembly.Location), // System 
     new AssemblyFileReference(typeof(IOrderedQueryable<>).Assembly.Location), // System.Data 
     new AssemblyFileReference(typeof(DbContext).Assembly.Location) // EntityFramework 
    ) 
    .AddSyntaxTrees(syntaxTree); 

var dllPath = "car.dll"; 
using (var stream = File.OpenWrite(dllPath)) 
{ 
    compilation.Emit(stream); 
} 

var code = @"new Context();"; 
var scriptEngine = new ScriptEngine(new[] { new FileInfo(dllPath).FullName, "EntityFramework" }); 

var context = scriptEngine.Execute<DbContext>(code); 
+0

をengine - typeof(DbContext).Assembly.Location。それ以外の場合は完全に動作します。 – Betty

+0

作成したアセンブリをディスクに書き込まずにscriptengineにロードする方法を知っていますか?私がmemorystream - > bytes - >アセンブリメソッドで作成したアセンブリを渡すと、ScriptEngineは "Path can be be empty"例外をスローするようです。 – Betty

+2

ええ、それは不可能だと思われます。ダイナミックな組み立てで試してみましたが、うまくいかなかったのです。 – svick

関連する問題