Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get LinqPad to work with an EF Core context?

I am trying to figure out if there is something I am missing or some way to hack around the lack of support (yet) for Entity Framework Core DbContexts in LinqPad. I've compiled my code targeting 4.6.1 (as suggested on the LinqPad forum) and tried the "Entity Framework V7" driver, but as its name suggests, I don't believe it's up-to-date. It still asks for an app.config file or a connection string for the constructor.

Add context dialog

Since EF Core contexts use DbContextOptions for construction rather than connection strings, I was thinking I could possibly create a constructor overload that takes a connection string, but that doesn't handle the underlying database driver. Is there a way to specify a factory for constructing the context? Any other possibilities? I'm feeling lost without LinqPad.

like image 744
AJ. Avatar asked Jan 20 '17 21:01

AJ.


2 Answers

Latest EFCore 1.1 LINQPad driver (v1.1.1.1) can correctly use constructor that accepts string (when this option is selected in LINQPad).

So it's possible to add the following constructor:

public ApplicationDbContext(string connectionString) 
    : this(new DbContextOptionsBuilder<ApplicationDbContext>()
           .UseSqlServer(connectionString).Options)
    { }

This will hard link this context instance to sql server provider, but at least not to connection string. And in addition your app not likely will ever try to use this constructor, EF Core never expects/promotes a ctor. that accepts string.

For additional safety you could wrap this constructor in #if DEBUG ... #endif so that it never gets to production.

like image 133
FunkyOne Avatar answered Oct 11 '22 17:10

FunkyOne


The driver seems to be buggy / not updates at all. I found a way to bypass it by modifying the DbContext.

In theory, this should have worked, but it does not:

private string _connectionString;
public ApplicationDbContext(string connectionString) : base()
{
    _connectionString = connectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (_connectionString == null)
        base.OnConfiguring(optionsBuilder); // Normal operation

    // We have a connection string
    var dbContextOptionsBuilder = new DbContextOptionsBuilder();
    optionsBuilder.UseSqlServer(_connectionString);
    base.OnConfiguring(dbContextOptionsBuilder);
}

LinqPad EF Core driver keeps looking for the parameterless constructor even if you specify "Via a constructor that accepts a string". That seems like a bug in the driver.

So then I gave it what it wanted, a parameterless contructor. I had to hardcode the connection string since IoC/appsettings.json config reader is not loaded and I don't feel like loading that separately in the DbContext. But it works and lets me test EF Core queries in LinqPad off my model.

This works fine for me:

private bool _isDebug = false;
public ApplicationDbContext() : base()
{
    _isDebug = true;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!_isDebug)
        base.OnConfiguring(optionsBuilder); // Normal operation

    // We are in debug mode
    var dbContextOptionsBuilder = new DbContextOptionsBuilder();
    // Hardcoded connection string
    optionsBuilder.UseSqlServer("data source=XXXX;initial catalog=XXXX;persist security info=True;user id=XXXX;password=XXXX;MultipleActiveResultSets=True;App=EntityFramework");
    base.OnConfiguring(dbContextOptionsBuilder);
}

This is in addition to the existing public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } of course.

Edit: Be careful, it looks like this overrides default behavior, which may not be visible until you deploy to the server.

like image 43
Tedd Hansen Avatar answered Oct 11 '22 18:10

Tedd Hansen