2015-08-26 12 views
6

è possibile?Query LINQ dinamica per ottenere il valore Campo dal database

Public String Get_Filed_By_Id(string table_Name,String Field_Name,string PK_val) 
{ 
    string strRes=""; 
    using(mydbcontext db=new mydbcontext()) 
    { 
     var x=db.table_Name.Where(p=>p.Id=PK_val).FirstOrDefault().Field_Name; 
     strRes=Convert.Tostring(x); 
    } 
return strRes; 
} 

O

var x=(from o in db.table_Name where o.Id=PK_val select o.Field_Name).FirstOrDefault(); 

Qui, sto passando Table_Name, Column_Name e il valore della condizione (PK_val) per ottenere il Column_Name da Table_Name all'interno di una certa condizione (Id=Pk_val).

E 'possibile ??

+0

bene se avete bisogno di questo tipo di funzionalità la prima cosa nella mente è la riflessione (ma non all'interno IQueryable) : var tableItem = db.table_Name.Where (p => p.Id = PK_val) .FirstOrDefault(); var x = tableItem.GetType(). GetProperty (FieldName) .GetValue (tabelItem, null); – Den

+0

hai considerato l'utilizzo del pattern di repository? – Arash

+0

@Arashjo no, puoi mostrarmi la via, fare una risposta ?? –

risposta

8

E 'possibile ??

Sì, lo è.

primo luogo, alcuni aiutanti:

using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 

namespace YourNamespace 
{ 
    internal static class DbHelpers 
    { 
     public static object GetColumnById(this object dbContext, string tableName, string columnName, object id) 
     { 
      var table = (IQueryable)dbContext.GetType().GetProperty(tableName).GetValue(dbContext, null); 
      var row = Expression.Parameter(table.ElementType, "row"); 
      var filter = Expression.Lambda(Expression.Equal(Expression.Property(row, "Id"), Expression.Constant(id)), row); 
      var column = Expression.Property(row, columnName); 
      var selector = Expression.Lambda(column, row); 
      var query = Call(Where.MakeGenericMethod(row.Type), table, filter); 
      query = Call(Select.MakeGenericMethod(row.Type, column.Type), query, selector); 
      var value = Call(FirstOrDefault.MakeGenericMethod(column.Type), query); 
      return value; 
     } 
     private static readonly MethodInfo Select = GetGenericMethodDefinition< 
      Func<IQueryable<object>, Expression<Func<object, object>>, IQueryable<object>>>((source, selector) => 
      Queryable.Select(source, selector)); 
     private static readonly MethodInfo Where = GetGenericMethodDefinition< 
      Func<IQueryable<object>, Expression<Func<object, bool>>, object>>((source, predicate) => 
      Queryable.Where(source, predicate)); 
     private static readonly MethodInfo FirstOrDefault = GetGenericMethodDefinition< 
      Func<IQueryable<object>, object>>(source => 
      Queryable.FirstOrDefault(source)); 
     private static MethodInfo GetGenericMethodDefinition<TDelegate>(Expression<TDelegate> e) 
     { 
      return ((MethodCallExpression)e.Body).Method.GetGenericMethodDefinition(); 
     } 
     private static object Call(MethodInfo method, params object[] parameters) 
     { 
      return method.Invoke(null, parameters); 
     } 
    } 
} 

ed ora la vostra funzione:

public string Get_Field_By_Id(string table_Name, string field_Name, string PK_val) 
{ 
    using (var db = new mydbcontext()) 
     return Convert.ToString(db.GetColumnById(table_Name, field_Name, PK_val)); 
} 
1

In realtà non è possibile con EntityFramework (per quanto ne so). Se solo avessi bisogno del campo con il suo nome, avresti potuto usare la soluzione proposta da @ Den. Ma vuoi specificare anche il nome della tabella come parametro. Quindi ti suggerisco di utilizzare l'API standard Sql Connector e creare la stringa di query con i parametri forniti.

Controllare this link per l'utilizzo di standard sql connettore api.

0

No, ma in questo modo

Public String Get_Filed_By_Id(string table_Name,String Field_Name,string PK_val) 
{ 
    string strRes=""; 
    using(mydbcontext db=new mydbcontext()) 
    { 
     var x=db.table_Name.Where(p=>p.Id=PK_val).Select(b=>b.Field_Name).FirstOrDefault(); 
     strRes=Convert.Tostring(x); 
    } 
return strRes; 
} 
+0

Non funzionerà, sto cercando di passare il 'Table_Name' e 'Field_value' come un' Parametro' –

+0

quindi utilizzare la query, come db.database.ExecuteSQLQuery o qualcosa del genere che prende una stringa (query) come parametro. – Lali

+0

credo in questo modo, ma credo che sarebbe ampio, ma voglio vedere la strada. –

1

ho avuto questa domanda troppo, so che questo non è esattamente quello che vuoi e bisogno di scrivere codice più ma è molto più pulito di quelli che vuoi scrivere.
Utilizzo del modello di repository
Per ogni tabella è necessario disporre di una classe modello e di una classe repository.
Considerate questo codice (il codice da un mio progetto)
Questo è il mio commento tavolo (questo può essere qualsiasi cosa con o senza proprietà di navigazione)

public sealed class Comment 
{ 
    public string CommentText { get; set; } 
    public DateTime PostDate { get; set; } 
    public int PostId { get; set; } 
    public int? PageId { get; set; } 
    public Page Page { get; set; } 
    public User User { get; set; } 
    public string UserId { get; set; } 
    public int? ParentId { get; set; } 
    public Comment[] ChildComments { get; set; } 
} 

RepositoryComment

public sealed class CommentRepository : BaseRepository<Comment> 
{ 
    public CommentRepository(BabySitterContext context) 
     : base(context) 
    { 
    } 
} 

e una base classe che si invia la query con nome tabella (qui modello) e campo (è possibile estendere Clas per ulteriori funzionalità)

public class BaseRepository<T> where T : class 
{ 
    protected BabySitterContext Context; 
    private readonly PluralizationService _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en")); 
    public BaseRepository(BabySitterContext context) 
    { 
     this.Context = context; 
    } 
    public bool Add(T t) 
    { 
     Context.Set<T>().Add(t); 
     Context.SaveChanges(); 
     return true; 
    } 
    public bool Update(T t) 
    { 
     var entityName = GetEntityName<T>(); 

     object originalItem; 
     var key = ((IObjectContextAdapter)Context).ObjectContext.CreateEntityKey(entityName, t); 
     if (((IObjectContextAdapter)Context).ObjectContext.TryGetObjectByKey(key, out originalItem)) 
     { 
      ((IObjectContextAdapter)Context).ObjectContext.ApplyCurrentValues(key.EntitySetName, t); 
     } 
     Context.SaveChanges(); 
     return true; 
    } 
    public void Attach(T t) 
    { 
     if (t == null) 
     { 
      throw new ArgumentNullException("t"); 
     } 

     Context.Set<T>().Attach(t); 
     Context.SaveChanges(); 
    } 
    public void Remove(T t) 
    { 
     if (t == null) 
     { 
      throw new ArgumentNullException("t"); 
     } 
     Context.Set<T>().Remove(t); 
     Context.SaveChanges(); 
    } 
    public IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "") 
    { 
     IQueryable<T> query = Context.Set<T>(); 

     if (filter != null) 
     { 
      query = query.Where(filter.Expand()); 
     } 

     foreach (var includeProperty in includeProperties.Split 
      (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
     { 
      query = query.Include(includeProperty); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 
    } 
    private string GetEntityName<TEntity>() where TEntity : class 
    { 
     return string.Format("{0}.{1}", ((IObjectContextAdapter)Context).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name)); 

    } 

    public virtual IEnumerable<T> GetByBusinessKey(T entity) 
    { 
     return null; 
    } 
}  

Per qualsiasi altra tabella solo fare classe del modello e reposiotry poi inherite dalla classe base

Utilizzando il codice

var context = new BabySitterContext(); 
var _commentRepository = new CommentRepository(context); 
var comment = _commentRepository.Get(x => x.PostId == id).FirstOrDefault(); 
Problemi correlati