Domanda

Sto tentando di creare un visualizzatore / editor di tabelle generico per un'applicazione MVC 6.

Attualmente uso

Context.GetEntityTypes();

Per restituirmi un elenco di tabelle.

Ora ho bisogno di recuperare i dati per un tipo specifico. La mia attuale implementazione è:

// On my context
public IQueryable<dynamic> GetDbSetByType(string fullname)
{
    Type targetType = Type.GetType(fullname);

    var model = GetType()
        .GetRuntimeProperties()
        .Where(o =>
            o.PropertyType.IsGenericType &&
            o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
            o.PropertyType.GenericTypeArguments.Contains(targetType))
        .FirstOrDefault();

    if (null != model)
    {
        return (IQueryable<dynamic>)model.GetValue(this);
    }

    return null;
}

Con questo codice nel mio controller

[HttpGet("{requestedContext}/{requestedTable}/data")]
public IActionResult GetTableData(string requestedContext, string requestedTable)
{
    var data = Request.Query;
    var context = GetContext(requestedContext);

    if (context == null)
    {
        return new ErrorObjectResult("Invalid context specified");
    }
    var entity = context.GetEntity(requestedTable);

    if (entity == null)
    {
        return new ErrorObjectResult("Invalid table specified");
    }

    var set = context.GetDbSetByType(entity.ClrType.AssemblyQualifiedName);

    if (set == null)
    {
        return new ErrorObjectResult("Invalid table specified - DbSet could not be found");
    }

    var start = Convert.ToInt32(data["start"].ToString());
    var count = Convert.ToInt32(data["length"].ToString());
    var search = data["search[value]"];

    return new ObjectResult(set.Skip(start).Take(count));
}

Così com'è, questo restituirà i dati del count della lunghezza e start posizione. Tuttavia, non posso eseguire query sulle proprietà specifiche di IQueryable<dynamic> .

Il problema è:

  1. Sembra una cosa banale da fare, quindi sono quasi sicuro che mi manca qualcosa - questo deve essere facile da fare.
  2. Se non è 1, allora come posso convertire il mio object set su un DbSet<T> modo da poter eseguire le mie query? Se ho impostato un punto di interruzione e ispezionato, posso vedere tutti i miei dati seduti lì.

NOTA: Questo è EF7

INFORMAZIONI ADDIZIONALI:

  1. Il <mysystem>.Models.Shared.Users requestedTable è il tipo EG completo: <mysystem>.Models.Shared.Users

EDIT (2016/5/5)

Ho finito per fare tutto in un semplice SQL - se qualcuno riesce a farlo funzionare per favore fammi sapere!

Risposta popolare

Ciò sarebbe più semplice utilizzando un metodo generico e utilizzando DbContext.Set<TEntity>() . È possibile creare un metodo generico in fase di esecuzione come questo:

public IActionResult GetTableData(string requestedContext, string requestedTable)
{
    var context = GetContext(requestedContext);

    if (context == null)
    {
        return new ErrorObjectResult("Invalid context specified");
    }
    var entity = context.GetEntity(requestedTable);

    if (entity == null)
    {
        return new ErrorObjectResult("Invalid table specified");
    }

    var boundMethod = s_getTableDataMethodInfo.MakeGenericMethod(entity.ClrType);
    return boundMethod.Invoke(this, new object[] { context }) as IActionResult;
}

private static readonly MethodInfo s_getTableDataMethodInfo
    = typeof(MyController).GetTypeInfo().GetDeclaredMethod("GetTableDataForEntity");

private IActionResult GetTableDataForEntity<TEntity>(DbContext context)
    where TEntity : class
{
    var data = Request.Query;
    var start = Convert.ToInt32(data["start"].ToString());
    var count = Convert.ToInt32(data["length"].ToString());
    var search = data["search[value]"];

    return new ObjectResult(context.Set<TEntity>().Skip(start).Take(count));
}


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché