简体   繁体   中英

Entity Framework Core get data from stored procedure and then convert into view model without DbSet

I have a function in the repository, GetForms , the purpose of the function is to call a stored procedure and return rows with data. Everything is working fine until now.

Function

public IEnumerable<FormBO> GetForms() 
{
      var id = "1"
      var Query= _context.FormBO.FromSqlRaw("dbo.SP_Core  @pin_ID={0}", id)
                                .AsNoTracking().ToList(); //3K line of sp
      return Query;
}

Model

public class FormBO
{
    [Key]
    public int? ID { get; set; }
    public int? secondid { get; set; }
    ......
}

DbContext

Added this code, so context thinks it is a table in the database and, I don't have to do more stuff

 public virtual DbSet<FormBO> FormBO { get; set; }

The problem

Whenever we scaffold the database and the db context, it regenerates all the files and code, so it removes the

  public virtual DbSet<FormBO> FormBO { get; set; }

And we have to add this line manually is there any way I can change the logic, so I don't have to add this code ( DBset<FormBO> ) to DbContext every time a dba updates the database...

What I found

I found that if I change the model to ".Database" and FromSqlRaw to ExecuteSqlRaw , but it is just returning the count as int not a list of rows.

public IEnumerable<FormBO> GetForms() 
{
    var id = "1"
    var Query = _context.Database.ExecuteSqlRaw("dbo.SP_Core  @pin_ID={0}", id)
                                 .AsNoTracking().ToList(); //3K line of sp
     return Query;
}

If it is possible it automatically add the DBSet to context whenever we update the code which I don't think we will able to do.

or

Get the query result without the dbset model and then I will use foreach loop to add it in FormBO model it is just 10 rows

Since the table doesn't actually exist in the database, the built in scaffolding process won't attempt to create it.

However you could probably replace the IScaffoldingModelFactory service, with an implementation that extends RelationalScaffoldingModelFactory , and use the code-first fluent api to define meta data for tables that don't really exist.

You could probably use this type of approach to define types for all table values in the database. Since EF Core 5 is adding support for table values, maybe they'll do it for you, but I haven't tested that.

public class MyModelFactory : RelationalScaffoldingModelFactory
{
    public MyModelFactory(
        IOperationReporter reporter, 
        ICandidateNamingService candidateNamingService, 
        IPluralizer pluralizer, 
        ICSharpUtilities cSharpUtilities, 
        IScaffoldingTypeMapper scaffoldingTypeMapper, 
        LoggingDefinitions loggingDefinitions) 
    : base(reporter, candidateNamingService, pluralizer, cSharpUtilities, scaffoldingTypeMapper, loggingDefinitions)
    {
    }

    protected override ModelBuilder VisitDatabaseModel(ModelBuilder modelBuilder, DatabaseModel databaseModel)
    {
        modelBuilder.Entity<FormBO>(entity =>
        {
            // ...
        });

        return base.VisitDatabaseModel(modelBuilder, databaseModel);
    }
}

    services.AddDbContextPool<ContextType>(o =>
    {
        o.ReplaceService<IScaffoldingModelFactory, MyModelFactory>();
        // ...
    });

Of course there's an easy answer too. The scaffolded context is a partial class. Just define your other DbSet in another source file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM