简体   繁体   中英

LINQ - Foreign Key Data and Expression Trees

First time posting. Apologies if I missed something. I have a .NET MVC program that accepts any number of filters from the user and then attempts to retrieve data from the model based on those filters. I've had success with Dynamic LINQ and Expression Trees but only when evaluating fields on my parent model (Insured). I can't seem to figure out how to correctly access the child model (Quote) through LINQ that's linked to the Insured model via a Foreign Key relationship. My db models:

    public class Insured {
        [Key]
        [Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public long INS_CLIENT_ID { get; set; }

        [Key]
        [Column(Order = 1)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public string INS_AGENT_ID { get; set; }

        [Key]
        [Column(Order = 2)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public long INS_UNQ_ID { get; set; }

        [Column("INS_NAME")]
        public string INS_NAME { get; set; }

        [ForeignKey("QTE_CLIENT_ID, QTE_AGENT_ID, QTE_INS_UNQ_ID")]
        public virtual ICollection<Quote> TBL_QTE { get; set; }
    }

    public class Quote {
        [Key]
        [Column(Order = 0)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public long QTE_CLIENT_ID { get; set; }

        [Key]
        [Column(Order = 1)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public string QTE_AGENT_ID { get; set; }

        [Key]
        [Column(Order = 2)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public long QTE_INS_UNQ_ID { get; set; }

        [Key]
        [Column(Order = 3)]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public long QTE_NUMBER { get; set; }

        [Column("QTE_LOB")]
        public string QTE_LOB { get; set; }

        [Column("QTE_CO_CODE")]
        public string QTE_CO_CODE { get; set; }

    }

I then have a LINQ in my controller file that populates a View model:

m.Insureds = (from i in repository.Insureds
              orderby i.INS_NAME
              select i).Where(GetWhere(s));

And my GetWhere function looks like such (which accepts a different View model of search options):

private Expression<Func<Insured, bool>> GetWhere(SearchOptions s) {
   ParameterExpression pe = Expression.Parameter(typeof(Insured));
   Expression left = Expression.Call(Expression.PropertyOrField(pe, "INS_AGENT_ID"), "ToUpper", null);
   Expression right = Expression.Constant(s.AgentId.ToUpper());
   Expression e1 = Expression.Equal(left, right);

   return Expression.Lambda<Func<Insured, bool>>(e1, pe);
}

All that works fine. I just can't extend it to be able to interrogate TBL_QTE fields. I tried...

m.Insureds = (from i in repository.Insureds
              where i.TBL_QTE.AsQueryable<Quote>().All<Quote>(GetLob(s))
              orderby i.INS_NAME
              select i);

where GetLob is ...

private Expression<Func<Quote, bool>> GetLob(SearchOptions s) {
    ParameterExpression pe = Expression.Parameter(typeof(Quote));
    Expression left = Expression.Call(Expression.PropertyOrField(pe, "QTE_LOB"), "ToUpper", null);
    Expression right = Expression.Constant(s.LOBCode.ToUpper());
    Expression e1 = Expression.Equal(left, right);

    return Expression.Lambda<Func<Quote, bool>>(e1, pe);
}

... but that's not quite right, either, as the Where is expecting the Expression.Lambda result, not a call to it. I just don't know how to simulate the navigation to the TBL_QTE properties through an Expression Tree. My gut tells me that I'm close with this line, but just not quite there, as it yields a 1025 Data Provider error:

i.TBL_QTE.AsQueryable<Quote>().All<Quote>(GetLob(s))

It looks like you may need to use the "let" keyword c# linq supports,

Here is an example (from LinqPad)

from p in Products let spanishOrders = p.OrderDetails .Where (o => o.Order.ShipCountry == "Spain") where spanishOrders.Any() orderby p.ProductName select new {
p.ProductName,
TotalValue = spanishOrders .Sum (o > => o.UnitPrice * o.Quantity) }

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