How to call method with Expression of type Func as parameter

爱⌒轻易说出口 提交于 2019-12-23 18:32:04

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!