2012-02-05 39 views
5

Chỉ cần một chút ý tưởng tôi đang chơi với, không chắc chắn liệu nó có khả thi hay có nhiều công dụng hay không.Tạo EF CodeFirst DbContext sử dụng Roslyn

Tôi đang cố gắng tạo cơ sở dữ liệu EF Code First cơ bản bằng cách sử dụng Roslyn CTP.

Code:

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(); 

Khi thực hiện tôi nhận được ngoại lệ sau đây

Ngoại lệ:

Loại 'Nộp # 0 + Xe' không được ánh xạ. Kiểm tra xem loại đã không được loại trừ một cách rõ ràng bằng cách sử dụng phương thức Bỏ qua hoặc chú thích dữ liệu NotMappedAttribute. Xác minh rằng loại đã được định nghĩa là một lớp, không phải là nguyên thủy, lồng nhau hoặc chung chung, và không kế thừa từ EntityObject.

Nhìn qua danh sách các vấn đề có thể xảy ra, tôi đoán Roslyn đang tạo lớp lồng nhau như một phần của gen mã. Điều này có ý nghĩa nếu không thì "Ngữ cảnh mới()"; cuộc gọi sẽ cần phải được đưa vào một lớp/phương pháp của một số loại. Tôi có thể phát ra một hội đồng, mà sẽ xác nhận ở trên nhưng có khả năng sẽ không có bất kỳ manh mối nào về cách viết nó một cách chính xác.

Tôi cũng đã đi xuống các tuyến đường của Syntax.ClassDeclaration, nhưng kết thúc với một vài trăm dòng mã chỉ để làm cho một lớp học với 1 tài sản và không có cách rõ ràng làm thế nào để nhanh chóng lớp đó.

Câu hỏi

Có một cách dễ dàng để tạo ra một lớp trong Roslyn có thể truy cập công khai (ví dụ như không lồng nhau trong lớp khác)?

Trả lời

5

Bạn có thể sử dụng Roslyn để tạo thư viện DLL thực tế có chứa loại của bạn dựa trên mã nguồn của bạn và sau đó sử dụng từ kịch bản của bạn:

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

cần thiết một sửa đổi nhỏ, đi qua đường dẫn đầy đủ của EF để kịch bản engine - typeof (DbContext) .Assembly.Location. Nếu không nó hoạt động hoàn hảo. – Betty

+0

biết bất kỳ cách tải nào đã tạo assembly vào scriptengine mà không cần ghi nó vào đĩa? ScriptEngine dường như ném một ngoại lệ "Đường dẫn không thể để trống" nếu tôi truyền một assembly được tạo bởi phương thức assembly -> bytes -> assembly. – Betty

+2

Vâng, có vẻ như điều đó là không thể. Tôi đã thử nó với lắp ráp năng động, và nó đã không làm việc hoặc. – svick

Các vấn đề liên quan