Начальный ie запрос - PullRequest
0 голосов
/ 05 мая 2020

Мне нужно динамически изменять имя таблицы в зависимости от года параметра. Например, в 2019 году:

var qry= db.Forms2019.Where(x=>x.Active==true).OrderBy(x=>x.Name)

в 2020 году:

vary qry= db.Forms2020.Where(x=>x.Active==true).OrderBy(x=>x.Name);

Итак, я использую корпус переключателя. У меня вопрос, как здесь инициализировать qry?

 public ActionResult Index(string year){
    var qry=??;
    switch(year){
         case "2019": 
             qry=db.Forms2019;
             break;
         case "2020":
            qry=db.Forms2020;
            break;
       }
      return View(qry);
 }

1 Ответ

1 голос
/ 05 мая 2020

Использование switch нормально (это то, как я бы это сделал), но я бы сделал это так:

(Вы можете использовать switch-expression , чтобы сделать это более лаконично, но для этого требуются C# 8.0 и. NET Core 3.0, но вы отметили свой вопрос asp.net-mvc, что означает, что вы, вероятно, используете C# 7.x самое позднее (как ASP. NET MVC не работает. NET Ядро, и вы не можете использовать C# 8.0 с ASP. NET MVC)

Этот подход работает, только если все таблицы содержат один и тот же тип сущности (или типы ковариантны):

public async Task<ActionResult> Index( Int32? year ) {

    // I assume Forms2019, Forms2020, etc all use the `Form` entity type:
    IQueryable<Form> query = this.GetBaseQuery( year ?? DateTime.Utc.Year );
    if( query is null )
    {
        return this.NotFound( message: $"No forms for the year {year} exist." );
    }

    List<Form> list = await query
        .Where( f => f.Active )
        .OrderBy( f => f.Name )
        .ToListAsync()
        .ConfigureAwait(false);

    return this.View( model: list );
 }

private IQueryable<Form> GetBaseQuery( Int32 year )
{
    switch( year )
    {
    case 2019:
        return this.db.Forms2019;
    case 2020:
        return this.db.Forms2020;
    default:
        return null;
    }
}

Обновление:

Очевидно, Forms2019 и Forms2020 возвращают разные типы сущностей, что означает, что вы не можете используйте одну переменную IQueryable<Form2019> для хранения запроса IQueryable<Form2020>.

Решение состоит в использовании интерфейса - к счастью, Entity Framework и Linq обычно поддерживают это:

Сначала определите interface IForm с теми членами, которые мы хотим запросить по:

interface IForm
{
    Boolean Active { get; }
    String  Name   { get; }
}

partial class Form2019 : IForm
{
}

partial class Form2020 : IForm
{
}

Затем измените код выше на этот:

public async Task<ActionResult> Index( Int32? year ) {

    // I assume Forms2019, Forms2020, etc all use the `Form` entity type:
    IQueryable<IForm> query = this.GetBaseQuery( year ?? DateTime.Utc.Year );
    if( query is null )
    {
        return this.NotFound( message: $"No forms for the year {year} exist." );
    }

    List<IForm> list = await query
        .Where( f => f.Active )
        .OrderBy( f => f.Name )
        .ToListAsync()
        .ConfigureAwait(false);

    return this.View( model: list );
 }

private IQueryable<IForm> GetBaseQuery( Int32 year )
{
    switch( year )
    {
    case 2019:
        return (IQueryable<IForm>)this.db.Forms2019; // This works because IQueryable<T> is covariant over T.
    case 2020:
        return (IQueryable<IForm>)this.db.Forms2020;
    default:
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...