0

I have Person entity which has a 1 : N relationship with Person_Addresses (fields: PersonID, AddressID, ValidFrom). I want to get all Person records and associated Person_Addresses with only latest ValidFrom. How should I do this using ObjectQuery or IQueryable?

Edit: I mentioned ObjectQuery and IQueryable, because I wanted to have a solution using extension methods (I think, that how it's called). Also I forgot to mention that I'm using Entity Framework where I have the entities generated. I want to get a person object which has it's person_adress member eagerly loaded.

Here are the entities structure: Person members: int id, string firstname, string lastname, Partner_Address partneradress

Person_Address members: int personid, int adressid, date validfrom

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sys
  • 443
  • 1
  • 8
  • 28
  • Looks complicated but should it be? The generated SQL should look like this: SELECT [Id] ,[Firstname] ,[Lastname] ,prt.AdressID FROM [Person] p CROSS APPLY ( SELECT TOP(1) [PersonId],[AdressId],[ValidFrom] FROM [Person_Addresses] pa WHERE p.[Id] = pa.[PersonId] ORDER BY [ValidFrom] DESC ) prt – Sys Jun 23 '10 at 08:13

1 Answers1

1

Try the following.

I have the following entities.

    //Person Entity
    public class Person
    {
        public int PersonID  { get; set; }
        public string PersonName { get; set; }
    }

    //PersonAddress Entity
    public class PersonAddress
    {
        public int PersonID { get; set; }
        public int AddressID { get; set; }
        public DateTime ValidFrom { get; set; }
    }

Then fire the following query.

    //Get the latest ValidFrom for each person from PersonAddress.
    var getLatestDateRecords =
    from p in lstPersonAddress
    group p by p.PersonID into g
    select new
    {
        Infos =
            (from PA in g
            select new
            {
                PersonId = PA.PersonID
                Date = g.Max(t=>t.ValidFrom)
            }).Distinct()
    };

    //Segregate the ValidFroms and PersonId from the
    //previous record set(getLatestDateRecords).
    var segRecords =
        from x in getLatestDateRecords
        from y in x.Infos
        select new { Date = y.Date, PersonId = y.PersonId };

    //Obtain all the relevant information from the PersonAddress
    // for the latest ValidFrom dates.
    var allValidRecords =
        from PA in lstPersonAddress
        join x in segRecords
        on PA.ValidFrom equals x.Date
        where PA.PersonID == x.PersonId
        select new {
                PersonId = PA.PersonID
                , AddressId = PA.AddressID
                , Date = PA.ValidFrom
            };

    //Get the final result
    var resultSet =
        from p in lstPerson
        join x in allValidRecords
        on p.PersonID equals x.PersonId
        select new
        {
            PersonId = p.PersonID
            ,PersonName = p.PersonName
            ,AddressId = x.AddressId,
            Date = x.Date
        };

I found it to be working fine with some test data.

Let me know in case of any concern.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • Well I think that you got the idea as how I did that. I don't think that it will be a problem for you to suit your requirement. You can take a look into the Entites upon which I have fired the Linq. It looks very similar that of yours. Hope you can proceed further without much hassel. All the best –  Jun 23 '10 at 06:35
  • Hi, this is a tested program. You can even go ahead with some sample. And more over, it has been done into pieces for the sake of understanding. –  Jun 23 '10 at 08:48
  • I happened to come accros this thread: http://stackoverflow.com/questions/584820/how-do-you-perform-a-left-outer-join-using-linq-extension-methods/584836#584836 I wonder if it's possible to join 2 different querys using groupjoin? something like: PersonQuery.GroupJoin(... PersonAddressQuery ...) – Sys Jun 24 '10 at 09:33