问题
I used Repository pattern that I saw on online tutorial...
Everything works fine except for find method, I have no idea how to work with this and I'm having hard time understanding Expressions or Func types. I used linq and lambda before but I'm begginer and still don't use it fluently...
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return Context.Set<TEntity>().Where(predicate);
}
I have this model class:
public partial class Artikl
{
[Browsable(false)]
public int IDArtikli { get; set; }
public string Barkod { get; set; }
[DisplayName("Šifra")]
public Nullable<int> Sifra { get; set; }
public string Naziv { get; set; }
[DisplayName("JM")]
public string JedinicaMjere { get; set; }
public decimal Tarifa { get; set; }
[DisplayName("Prodajna")]
public Nullable<decimal> ProdajnaCijena { get; set; }
[Browsable(false)]
public Nullable<bool> Flag { get; set; }
public Nullable<decimal> Kalo { get; set; }
[DisplayName("Nabavna")]
public Nullable<decimal> NabavnaCijena { get; set; }
[DisplayName("Veleprodajna")]
public Nullable<decimal> VeleprodajnaCijena { get; set; }
public Nullable<decimal> Zalihe { get; set; }
}
My question is how can I get the Artikl item based on property "Sifra". I have no idea how to call this method...
private void txtSifra_TextChanged(object sender, EventArgs e)
{
var artikl = _UnitOfWork.Artikl.Find(???);
txtNaziv.Text = artikl.Naziv;
}
回答1:
You need to pass a lambda expression to satisfy Expression<Func<TEntity, bool>> predicate
. You can get the item based on property "Sifra" by doing this:
var artikl = _UnitOfWork.Artikl.Find(q => q.Sifra == "some int value").FirstOrDefault();
Hope it helps!
回答2:
Other answers already explained how to use expression but I want to mention one thing that is often overlooked when using so-called repository pattern:
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return Context.Set<TEntity>().Where(predicate);
}
This returns IEnumerable<TEntity>
and because of that this:
var result = _UnitOfWork.Artikl.Find(c => c.Sifra == 1).FirstOrDefault()
Will not execute whole query in database. The database query will look (roughly) like this:
select * from Artikl where Sifra = 1 -- < not efficient
and not like this:
select top 1 * from Artikl where Sifra = 1 -- < efficient
To fix this issue you have to either return IQueryable
:
public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return Context.Set<TEntity>().Where(predicate);
}
Or make separate method for every query you are going to make:
public TEntity FindFirst(Expression<Func<TEntity, bool>> predicate)
{
return Context.Set<TEntity>().Where(predicate).FirstOrDefault();
}
回答3:
The usage of Expression<Func<TEntity, bool>>
is like so, just pass in a lambda expression (pseudo-code):
var result = context.set.Find(x => x.Property == value);
So in your case:
var artiklList = _UnitOfWork.Artikl.Find(x => x.Sifra == 1);
var artikl = artiklList.FirstOrDefault();
Don't forget to return .FirstOrDefault()
as the Find
result will be an IEnumerable<T>
.
来源:https://stackoverflow.com/questions/42575888/how-to-call-method-with-expression-of-type-func-as-parameter