Создание EF CodeFirst DbContext с использованием Roslyn - PullRequest
5 голосов
/ 05 февраля 2012

Просто небольшая идея, с которой я играю, но не уверен, что она жизнеспособна или полезна.

Я пытаюсь создать очень простую базу данных EF Code First с использованием Roslyn CTP.

Код:

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.

Просматривая список возможных проблем, я предполагаю, что Рослин делаетвложенный класс как часть кода gen.Это имеет смысл, в противном случае "new Context ();"вызов должен быть заключен в некоторый класс / метод.Я мог бы создать сборку, которая подтвердила бы вышеизложенное, но, вероятно, не имела бы никаких подсказок о том, как правильно ее написать.

Я также пошел по пути Syntax.ClassDeclaration, но в итоге получил несколько сотенстрок кода только для создания класса с 1 свойством и без очевидного способа создания экземпляра этого класса.

Вопрос

Существует ли простой способ создать класс вРослин, который общедоступен (например, не вложен в другой класс)?

1 Ответ

5 голосов
/ 05 февраля 2012

Вы можете использовать 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);
...