Bet*_*tty 5 ef-code-first roslyn
只是一个小小的想法,我正在玩,不知道它是否可行或有多大用处.
我正在尝试使用Roslyn CTP生成一个非常基本的EF Code First数据库.
码:
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();
Run Code Online (Sandbox Code Playgroud)
执行时,我得到以下异常
例外:
未映射"提交#0 + Car"类型.使用Ignore方法或NotMappedAttribute数据批注检查未明确排除类型.验证类型是否已定义为类,不是原始类,嵌套类还是通用类,并且不从EntityObject继承.
通过查看可能出现的问题列表,我猜测Roslyn正在将嵌套类作为代码生成的一部分.这有意义,否则"新的Context();" 调用需要包装到某种类/方法中.我可以发出一个程序集,这将确认上述内容,但可能没有任何关于如何正确编写它的线索.
我也走了Syntax.ClassDeclaration的路线,但最终得到了几百行代码,只是为了创建一个具有1个属性的类,并且没有明显的方法来实例化该类.
题
是否有一种简单的方法可以在Roslyn中创建一个可公开访问的类(例如,不嵌套在另一个类中)?
您可以使用Roslyn根据源代码创建包含类型的实际DLL库,然后使用脚本中的类型:
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);
Run Code Online (Sandbox Code Playgroud)