简体   繁体   中英

How to call method with Expression of type Func as parameter

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

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

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!

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> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM