2015-08-26 16 views
6

jest to możliwe?Dynamiczne zapytanie LINQ, aby uzyskać wartość pola z bazy danych

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; 
} 

LUB

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

Tutaj jestem przechodzącej Table_Name, Column_Name i wartość Warunek (PK_val), aby uzyskać Column_Name z Table_Name w pewien warunek (Id=Pk_val).

Czy to możliwe?

+0

dobrze, jeśli potrzebujesz tego rodzaju funkcjonalności pierwszą rzeczą, na umysł jest odbicie (ale nie wewnątrz IQueryable) : var tableItem = db.table_Name.Where (p => p.Id = PK_val) .FirstOrDefault(); var x = tableItem.GetType(). GetProperty (FieldName) .GetValue (tableItem, null); – Den

+0

czy rozważałeś użycie wzorca repozytorium? – Arash

+0

@Arashjo nie, możesz pokazać mi drogę, złożyć odpowiedź? –

Odpowiedz

8

Czy to możliwe ??

Tak, jest.

pierwsze, niektóre pomocników:

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); 
     } 
    } 
} 

i teraz swoją funkcję:

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

To naprawdę nie jest możliwe z EntityFramework (o ile wiem). Jeśli potrzebujesz tylko pola po nazwie, możesz użyć rozwiązania zaproponowanego przez @ Den'a. Ale chcesz również podać nazwę tabeli jako parametr. Sugeruję więc, abyś użył standardowego interfejsu API łącznika Sql i zbudował ciąg zapytania z podanymi parametrami.

Sprawdzanie this link pod kątem korzystania ze standardowego interfejsu API złącza sql.

0

No, ale w ten sposób

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

Nie działam, próbuję przekazać 'Table_Name' i 'Field_value' jako' Parameter' –

+0

następnie użyć zapytania, jak db.database.ExecuteSQLQuery lub coś podobnego do tego, które pobiera ciąg znaków (zapytanie) jako parametr. – Lali

+0

wierzę w ten sposób, ale myślę, że byłby szeroki, ale chcę zobaczyć drogę. –

1

miałem na to pytanie też, wiem, że to nie jest dokładnie to, co chcesz i trzeba pisać więcej kodu ale jest o wiele czystszy niż te, które chcesz napisać. Używanie wzorca repozytorium
Dla każdej tabeli powinieneś mieć klasę modelu i klasę Repozytorium.
Rozważmy ten kod (ten kod od jednego z mojego projektu)
To jest mój komentarz stół (to może być coś z lub bez właściwości nawigacji)

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) 
    { 
    } 
} 

i zasady klasa, do której wysyłasz zapytanie z nazwą tabeli (tutaj model) i polem (możesz rozszerzyć klasę o większą funkcjonalność)

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; 
    } 
}  

Dla każdej innej tabeli po prostu zrobić klasę modelu i reposiotry następnie inherite z klasy bazowej

Korzystanie kod

var context = new BabySitterContext(); 
var _commentRepository = new CommentRepository(context); 
var comment = _commentRepository.Get(x => x.PostId == id).FirstOrDefault(); 
Powiązane problemy