问题
I have a very large, existing database with numerous views and tables. I need to combine the results of some views and tables. I want this combined data to be available in my DbContext but there is no single corresponding view or table that I can use to map the entity to the SQL results I want.
To this end, I have set up a DbQuery in my context and I am using the OnModelCreating method to set up the query results, an example is below.
Here are the entity object models. In this example Author
and Book
are tables and AuthorBookCount
is an object model of a custom SQL query that has no corresponding view or table to be mapped to.
public class Author
{
[Column("ID")]
public int Id { get; set; }
[Column("FIRST_NAME")]
public string FirstName { get; set; }
[Column("LAST_NAME")]
public string LastName { get; set; }
}
public class Book
{
[Column("ID")]
public int Id { get; set; }
[Column("AUTHOR_ID")]
public int AuthorId { get; set; }
[Column("TITLE")]
public string Title { get; set; }
}
public class AuthorBookCount
{
[Column("AUTHOR_FULL_NAME")]
public string AuthorFullName { get; set; }
[Column("BOOK_COUNT")]
public long BookCount { get; set; }
}
Then I set up the DbContext
like this:
public class MyDbContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
public DbQuery<AuthorBookCount> AuthorBookCounts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//Set up cnxn string
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<AuthorBookCount>().ToQuery(() =>
AuthorBookCounts.FromSql("SELECT DISTINCT(Authors.FIRST_NAME + ' ' + Authors.LAST_NAME) AS AUTHOR_FULL_NAME, COUNT(Books.Id) FROM Authors JOIN Books ON Books.AUTHOR_ID = Authors.ID GROUP BY (Authors.FIRST_NAME + ' ' + Authors.LAST_NAME)");
}
}
Now, when I try to make use of my AuthorBookCounts
property I get a SystemNotSupported exception with a message stating that FromSql is currently not supported.
I changed my FromQuery
SQL call to a LINQ query and it works. The issue with this solution is that my SQL calls are pretty complex and it is a huge pain to keep converting my SQL to a LINQ statement.
Any explanations as to what is happening or what I am doing wrong would be greatly appreciated.
回答1:
Like all great problems, the solution for this was quite simple. In the ToQuery
method, replace the reference to the DbQuery<AuthorBookCount>
property AuthorBookCounts
with another Query<T>
reference, like so.
public class MyDbContext : DbContext
{
public DbSet<Author> Authors { get; set; }
public DbSet<Book> Books { get; set; }
public DbQuery<AuthorBookCount> AuthorBookCounts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//Set up cnxn string
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<AuthorBookCount>().ToQuery(() =>
Query<AuthorBookCount>().FromSql(@"SELECT DISTINCT(Authors.FIRST_NAME + ' ' +
Authors.LAST_NAME) AS AUTHOR_FULL_NAME, COUNT(Books.Id) FROM Authors
JOIN Books ON Books.AUTHOR_ID = Authors.ID GROUP BY (Authors.FIRST_NAME + ' ' +
Authors.LAST_NAME)");
}
}
This resolved the specific error that I was experiencing above. Some important things to note that I learned along the way. These things should be pretty self explanatory if you have been using EF a lot.
- The SQL statement MUST return a value for every property in the entity object model that you are mapping the statement to.
- The object entity properties MUST be properly mapped to the field names returned in the SQL statement.
I hope this post helps someone else in their endeavors. A course that I found helpful was Julie Lerman's Entity Framework Core 2.1: What's New Playbook available on PluralSight.
来源:https://stackoverflow.com/questions/57965143/fromsql-with-non-existing-entity