So been a while since I posted last, and I’m sure everyone has been worried. Turns out that I’ve been banging my head against the wall named MVC. And man I have a slew of new posts back logged for when I have more time. However, due to the new project I’ve been working one, I forced myself to tackle Lazy Loading in the Entity Framework. Turns out the solution isn’t that hard since it has everything needed to make it work.

One of the biggest waaaaahbumlance calls is the fact that Entity Framework doesn’t have lazy loading. This isn’t true. It does, you just have to do a little work, which is to be expected from a FRAMEWORK. Now I have to admit, I wish there were a slightly less odd way of doing this, but eh it’s not too bad.

Say you have a class named Topic and it has a reference to a Forum class named ParentForum. Now this is just a property on the actual class created by the E-Work to represent a many to one foriegn key relationship between the Topic table and the Forum table. Now the problem comes in when you try to use something from that property like:

    Int32 someInt = topic.ParentForum.ForumId;

If you didn’t use the Include method when you got that topic:

    context.Include("ParentForum").Select(topic => topic);

You are screwed because the ParentForum property will return a null. So this forces you to use Include every time you want to get a Topic and access it’s ParentForum property. Sucks.

So next thought is to find out how to lazy load and then plunk it into that generated property. Eh I don’t know about you, but that sounds like a bad idea to mess around with a generated file. You have no idea when the E-Work will just trash the file and rebuild.

Next thought was to create a proxy property to check the real one and then load if it’s not already loaded. Something like:

    public Forum ParentForumLazyLoaded
    {
        get
        {
           //check and return
        }
    }

Ok so that’s not horrible except two things: The name looks dumb and people can still get at the original ParentForum property.

So in comes my solution and it’s pretty simple. Rename the property name on the class to something ParentForumInner and make it private.

bat_lazyload1

Then you can create a much nicer outward facing property like:

    public Forum ParentForum
    {
      get
      {
          if (!ParentForumInnerReference.IsLoaded)
          {
              ParentForumInnerReference.Load();
          }

        return ParentForumInner;
    }
    set
    {
        ParentForumInner = value;
    }
}

Now one of the issues with this is that although outside the class only the ParentForum property can be seen, within the class they both can be seen which can lead to issues like:

    context.Topics.Where(topic => topic.ParentForum.ForumId == id);  //boom

Where you should be using:

    context.Topics.Where(topic => topic.ParentForumInner.ForumId == id);  //yay

E-Work doesn’t know how to handle that situation when evaluating that expression and the kicker is that it does just fine compile time. You won’t know this is bad until runtime.

Other issue is that you have to do a little more work then just some setting on the property which is what most people wish for. I guess that may be true, but again this is a framework. It gives you all the tools you need to makes things work, you just have to do some coding.

The plus side to this is that with minimal coding, you can completely get rid of Include which to me is huge.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

So this may be a post that most good programmers will think, “Well duh” but as I’m a tool this finally caught me.

I’d always heard that ++ evaluates differently than +=1, but I’d never run into a situation that would turn the old light bulb on so I really didn’t care. Well I met that situation today.

I was writing a method that basically checks to see if all the dates in a list are in order by creating a dictionary, assigning the index as the key, and sorting by the date. I then convert the keys to an array and make sure that the index is the same as the key. After all, if the dates are in order, the keys should mimic an index.

  Key     Date
  0        6-27-2008
  1        6-28-2008
  2        6-29-2008

So that the new array would be:

  [0]    0
  [1]    1
  [2]    2

And if anything was out of order, you would get something like this:

  [0]    0
  [1]    2
  [2]    1

So the code is basically:

  int loopCounter = -1;

  IDictionary<DateTime> timeSequence =
                dateList
                .ToDictionary(item => loopCounter++);
  var sequenceList =
                 timeSequence
                 .OrderBy(item => item.Value)
                 .Select(item => item.Key).ToArray();
  return sequenceList.Any(item => item != sequenceList[item]);

Now right off the bat you’ll see that I used loopCounter ++. The thought was that in order to get this correctly inline (Meaning the key would mock an index) I would have to keep adding to the loopCounter. Well my thought was simply to use ++ and thus I would have to set the loopCounter to -1 at first otherwise the first key would be 1. Well that’s not what happened. Turned out it looked like:

  [0]  -1
  [1]   0
  [2]   1

Wait what? -1? But I added to it! And here was the catcher. Turns out in this situation, the ++ acts out like:

  • Set the key to what the loopCounter equals right now.
  • Add 1 too the loopCounter
  • Continue with loop

It actually set the key BEFORE adding the 1 to it. So in reality with this I really needed loopCounter to start at 0 OR use +=1 which would actually add the 1 THEN set the key to the value. Guess I should have paid more attention in school instead of checking NBA message boards.

Side note: Light bulb apparently is two words. I learned TWO things today.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

So found something interesting out the other day, and maybe you already knew this but I didn’t so I’m going to post about it.  Don’t like it?  Too bad.

One things nice about the Entity Framework is the ability to create or fill a class on the fly with the Linq query methods/language. You.. you have no idea what I’m trying to say. Fine. I’ll put it in programming speak:

  someList.Select(item => new { item.Name, item.ID })

  or

  from item in someList
  select new { item.Name, item.ID }

OR

  someList.Select(item => new DataItemClass { Name = item.Name, ID = item.ID })

  or

  from item in someList
  select new DataItemClass { Name = item.Name, ID = item.ID }

As you can see, they are two slightly different examples. One will create a list of anonymous types and the other a list of DataItemClass objects. Now that’s not really the point of this, the point is something like this:

  context.Topics
    .Select(topic =>
                new TopicItem
                {
                  TopicName = topic.Name ,
                  Creator = topic.User.UserName,
                  Category = topic.Category.Description
                }
              )

Now, here’s the thing that I assumed. When you select out a bunch of topics and you want to make sure that the one to on properties are “include”ed like thus:

  topicList
   .Include("User")
   .Include("Category")
   .Select(item => item);

Other wise when you try to access that User property you’ll get a null reference exception. So with this I thought that when you query like I did above to fill the TopicItem object, I would get the same problem as I would if I tried just accessing the property on a hydrated Topic. In other words:

  Creator = topic.User.UserName,

Would blow up mid query after all calling that property after a query would sans include. Come to find out, and I probably should have already known this, Entity Framework is just fine without having to have the Include method or any kind of join. Infact, adding the include method in the method chain:

  context.Topics
    .Include("User")
    .Include("Category")
    .Select(topic =>
                new TopicItem
                {
                  TopicName = topic.Name ,
                  Creator = topic.User.UserName,
                  Category = topic.Category.Description
                }
              )

Did nothing when I profiled the query. The SQL was exactly the same with or without the include. So it’s smart enough to know that if I am not actually hydrating an entire Topic object, it doesn’t need to bother with the includes. Go figure.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Website: Iconshock ( http://www.iconshock.com/ )
Description: From their website - Iconshock offers the largest icon collection over the internet, with nearly 500,000 unique icons (they don’t include sizes or file types in this estimation, only different and unique icons) with the highest quality and most of them including source files to allow you to make your own changes. All those icons are included in about 200 different collections with different design styles to choose from according to your application GUI.

Icons & Logos
Iconshock.com offers great looking icons and logos for reasonable prices. Both their icons and logos are of very high quality. Source files are also included so that you can modify them as needed. Personally, I am a fan of the Super Vista and Lumina sets. Iconshock offers the ability to purchase single sets or create your own bundle of sets to purchase at a reduced price. You can also subscribe and get all the icons they offer plus any new icons added during your subscription. The website is quick and easy to navigate. If you need a custom logo or icons created specifically for you, Iconshock can do that as well. I have been a web developer for over 10 years, and their portfolio of custom work is AMAZING!

Example Logo
Example Logo


The Community
What sets Iconshock apart from their competition is a community portal which rewards people for their participation. Each week, Iconshock allows users to vote on which free set of icons the community receives. Users can collect free icon sets by swapping with other members. Free sets can also be unlocked by earning points by simply logging in or posting in their forums. You can join the community on their website or by searching Twitter for #Iconshock. Recently, community members were recognized for their participation when they were awarded full icon sets. You can read more about these awards on the Iconshock Blog.

You can browse through some of their icons below:

Icon Set Specifics
Sizes

  • Normal: 256×256, 128×128, 72×72, 64×64, 48×48, 32×32, 24×24, 16×16 pixels (available in png only)
  • Hot: 128×128, 48×48, 32×32, 24×24, 16×16 pixels (available in png only)
  • Disable:128×128, 48×48, 32×32, 24×24, 16×16 pixels (available in png only)
  • ico:256×256, 128×128, 48×48, 32×32, 24×24, 16×16 pixels
  • gif :128×128, 48×48, 32×32, 24×24, 16×16 pixels
  • bmp:128×128, 48×48, 32×32, 24×24, 16×16 pixels

Color States

  • Normal: Normal color
  • Hot: Contrasted Colors, useful in rollovers, active buttons
  • Disabled: Gray Scale colors, useful in inactive buttons

Formats

  • PNG
  • GIF
  • ICO
  • BMP
Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading ... Loading ...

Get the total count of pages. | Get the real page number. | Using Skip and Take to Page | The Actual Paging Controls

Now onto the fourth part of this epic saga that George Washington once called, “The most astounding exercise in futility”

Ok so let’s say you have a grid, items to fill it with, and four buttons. Each button has a direction, say one back, all the way back, one forward, all the way forward. No big deal. Now you want them to page correctly when used. After all, it’s always a bonus when things go right. First you need to set the CommandArguments on the buttons themselves to whatever page they are responsible for.

private void SetAndBind(Int32 pageNumber)
{
  Int32 realPage;
  Int32 totalCount;

  IList<ToolItem> inviteList =
    ToolClass
    .GetSomeTools("Sean", 20, pageNumber, out realPage, out totalCountOfPages);

  btnFullBack.CommandArgument = Convert.ToString(0);
  btnOneBack.CommandArgument = Convert.ToString(realPage - 1);
  btnOneForward.CommandArgument = Convert.ToString(realPage + 1);
  btnFullForward.CommandArgument = Convert.ToString(totalCountOfPages);

  BindGrid(inviteList);
}

First off, GetSomeTools is just a method that is the same as I presented in the third installment of this epic saga that George Washington once called, “The most astounding exercise in futility”. If you’ve been reading up to this point, then you’ll know that. If not, you might have some reading to do.

So, here’s a simple method used to get the info we need (using the page number) and set the buttons. As seen before, realPage is the actual possible page (In case someone passed in page 21 when there are only 20 pages) and totalCountOfPages gives us how many possible pages there are. This makes setting the button CommandArguments cake. Now for the button event:

  private void btnPaging_Click(Object sender, EventArgs e)
  {
    SetAndBind(Convert.ToInt32(((Button)sender).CommandArgument));
  }

And then you just set all the click events to that:

  btnFullBack.Click += btnPaging_Click;
  btnOneBack.Click += btnPaging_Click;
  btnOneForward.Click += btnPaging_Click;
  btnFullForward.Click += btnPaging_Click;

And boom, you’re pretty much set.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Get the total count of pages. | Get the real page number. | Using Skip and Take to Page | The Actual Paging Controls

Ok so the last two posts have been arguably useless, maybe more so than anything else here, but they were somewhat needed because now I am going to show how to Linq, the Entity Framework, and well that’s it I think.

public static IList<ToolItem> GetSomeTools(String name, Int32 numberToShow, Int32 pageNumber, out Int32 realPage, out Int32 totalCountOfPages)
{
  //EntityContext.Context is just a singletonish version of the
  //Entities class.  Most people would use
  //  using (ToolEntities context = new ToolEnties())
  Int32 totalCount = EntityContext.Context.ToolItems
		   .Count(item => item.Name == name);
  //This is the method from the first post of this series
  //Just getting the count of pages based on numberToShow and
  //item totalCount
  totalCountOfPages = TotalCountOfPages(totalCount, numberToShow);
  //This is the method from the second post of this series
  //Basically getting the best possible page if the page number
  //is higher than the totalCountOfPages or lower than 0
  realPage = GetRealPage(totalCountOfPages, pageNumber);

  returnValue = EntityContext.Context.ChatRooms
			  .Where(item => item.Name == name )
			  .OrderBy(item => item.Name)
			  .Skip(numberToShow * realPage)
			  .Take(numberToShow)
			  .ToList();

  return returnValue.ToList();
}

Really simple yes? It follows like this:

Say I’m on page 1, which for this would be zero or pageNumber - 1. So I want to grab the first 20 items from the database. Well that means I want to start at 0 and grab 20. Now if you want this all to be done with some kind of conditional thing that either handles the first page or the other pages, you actually want to skip the same way no matter what the page number is. This is taken care of by numberToShow * realPage since even at 0 this works. After all 0 * anything is 0 and therefore you will be Skipping 0 items. So in other words, you’re at the start. Next you want to Take the amount of items you need, which is 20. Next time around you’ll start at 20 Skip(numberToShow 20 * realPage 1) and take the next 20. Nice thing is, even if you say Take 20 and there are only 2 left, it doesn’t care. It will just grab those two.

And there you have it, how to page with the Entity Framework and minimal amount of work. I know I hate taking other people’s methods (Like the TotalCountOfPages and GetRealPage methods), don’t know why. So sorry if I am forcing you to do so. However, the two methods I gave are semi important to this.

You might wonder why realPage and totalCountOfPages, well this is useful stuff when knowing what page is next for paging controls. Next post I’ll show those off but I’ll warn you, they are nothing spectacular.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Get the total count of pages. | Get the real page number. | Using Skip and Take to Page | The Actual Paging Controls

So in part one I posted the method to find the total count of pages you’ll need so that you don’t go too far while paging. Now it’s about trying to get the best possible page number despite what’s passed in.

Here’s the situation, when you are paging up or down, you want to make sure you don’t go lower than 0 or higher than whatever the total count of pages is. Sometimes though, things go wrong. They go very wrong. It’s possible that your ui design will allow for any number to be passed in as the page number (Too many reasons this could happen to bother with). Say you have only 10 possible pages but the number 12 gets passed in. Well you either allow it to grab a non existant page 12 or you have a method to determine the best possible choice at this point (10). Turns out it’s idiot simple… what? Were you expecting anything different?

public static Int32 GetRealPage(Int32 totalCountOfPages, Int32 pageNumber)
{
  //pageNumber and totalCountOfPages have to be above 0 or problems
  if (pageNumber > 0 && totalCountOfPages > 0)
  {
    //If page number is higher than the possible count of pages,
    //then you just need the total count to be the new page number...
    //but there's one more step
    pageNumber = totalCountOfPages < pageNumber ? totalCountOfPages : pageNumber;
    //If by chance the pageNumber now is the same as totalCountOfPages
    //(Meaning it was larger than totalCountOfPages originally)
    //1 has to be subtracted to make sure it's inline with a 0 based system where
    //page 1 is actually 0.  This will make more sense when using skip and take in
    //the next post.
    pageNumber = totalCountOfPages != pageNumber ? pageNumber : totalCountOfPages - 1;
  }
  else
  {
    pageNumber = 0;
  }

  return pageNumber;
}

Ok so I’m going to claim this is amazing stuff, but it will come in handy with the next post.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

Get the total count of pages. | Get the real page number. | Using Skip and Take to Page | The Actual Paging Controls

So something I’ve been doing a lot of lately is making quite possibly the best thing ever: String cheese wrapped in turkey bacon. But when I’m not doing that, I am working with a lot of ListViews and the entity framework. Now I know there are “built in” paging controls but I just haven’t liked what I’ve seen. So I took it upon myself one day to develop a repeatable system for paging. Say you have users and a bunch of invites that are attached to the users. You want to show a list of invites for a particular user, but you want a ListView that doesn’t show every invite… ie you need a pager. Well just so happens I have a solution, but as always you should consult a doctor before use.

First off you need a method to get the total count of pages meaning what the ceiling is when you page upwards. After all, if you go over the possible count of pages, you’ll just get no items returned and look kind of dumb.

There are three situations you have to look out for: You have less items that the required items per page (Say 10 rows but you display 20 row per page), you have a perfect division (20 rows and 20 row per page or 40 rows and 20 rows per page, ect), you have an uneven division (21 rows and 20 rows  per page). First two are easy, third isn’t hard exactly but there are some catches.

public static Int32 TotalCountOfPages(Int32 rowCount, Int32 neededPageSize)
{
  Int32 returnValue;
  if(rowCount > 0)
  {
    if (rowCount <= neededPageSize)
    {
      returnValue = 1;
    }
    else
    {
      if ((rowCount % neededPageSize) == 0)
      {
        returnValue = rowCount / neededPageSize;
      }
      else
      {
        Decimal convertedPageSize =
         Convert.ToDecimal(neededPageSize);
        Decimal convertedRowCount =
         Convert.ToDecimal(rowCount);
        Decimal resultRounded =
          Math.Round(convertedRowCount / convertedPageSize);
        Decimal resultNonRounded =
          convertedRowCount / convertedPageSize;

        if (resultRounded < resultNonRounded)
        {
           returnValue =
            Convert.ToInt32(resultRounded + 1);
        }
        else
        {
           returnValue =
            Convert.ToInt32(resultRounded);
        }
      }
    }
  }
  else
  {
    returnValue = 0;
  }
  return returnValue;
}

Ok so first off, I assume this one is pretty obvious:

  if(rowCount > 0)

If there aren’t any rows, the there can’t be a page count.

Next take care the less rows than being shown per page:

  if (rowCount <= neededPageSize)
  {
    returnValue = 1;
  }

Simple enough. Now for the second part, a perfect division between rows and rows to show:

 if ((rowCount % neededPageSize) == 0)
 {
    returnValue = rowCount / neededPageSize;
 }

Basically, for those who don’t know mod or the % operator, that means there is no remainder. If there were, the result of rowCount % neededPageSize would not be 0 since Mod basically means “Give me what’s left over when I divide something by something else.”

Ok, this is where it gets a little messy as I have yet to find a good way to round a number up since, far as I know, there’s no way to do it with the .Net lib’ary. So, I had to come up with something clever… and when that failed I came up with this:

 Decimal convertedPageSize =
    Convert.ToDecimal(neededPageSize);
 Decimal convertedRowCount =
    Convert.ToDecimal(rowCount);
  Decimal resultRounded =
    Math.Round(convertedRowCount / convertedPageSize);
  Decimal resultNonRounded =
    convertedRowCount / convertedPageSize;

  if (resultRounded < resultNonRounded)
  {
      returnValue =
          Convert.ToInt32(resultRounded + 1);
  }
  else
  {
     returnValue =
       Convert.ToInt32(resultRounded);
  }

Ok so what’s going on here? First off, because trying to divide an integer by an integer gives me an integer, I had to covert some stuff to decimal. Why is that? When I divide them, I need to know if the number after the decimal is between 1 and 1.5 since Math.Round will round down in that case killing my ability to tell if I have enough pages.

Example: 19 rows and 10 per page will give me a 1.9 which Round will make 2. This is perfect since I need two pages to show the 19 rows. What if I have 14 rows and 10 per page? I get 1 from rounding. Uh oh. I really need two pages.

How do I get around this? Get the rounded version and the unrounded version. From there I know that if the unrounded version is greater than the rounded version I need an extra page.

So 14 rows / 10 per page = 1.4 unrounded and 1 rounded. 1.4 > 1, so that 1 page isn’t going to do it. I need to add one more page. Now if it 19 rows/10 per page I’ll get 1.9 unrounded and 2 rounded. 2 pages is exactly what I need and I don’t have to add anything.

Next post I’ll show the next needed method: How to tell if the page number being sent in (From the pager/UI) is actually valid. If not, then grab the last possible amount of records.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

 So I ran into this error yesterday trying to delete a user which in turn has multiple collections that would be deleted too. You would think that I would have to manually delete the entire User tree, on collection at a time. Well the way thing work is that Entity framework will do the work for you if your tables are set to Cascade Delete. Now, you might see that error and be confused as to why it crops up even when you do have Cascade Delete on the needed tables. Here’s the situation:

As I said, I was trying to delete a user through the entity framework but noticed that all the addresses the user had were still in the database after deletion. Whoops. I dun forgot to set Cascade Delete on the tables. No big deal. So after I fixed the tables, I went to update the edmx file… ie update from database… and I thought all was well. Yeah not so much. I started to get this error. So the next thing I did was open the .edmx file in notepad and looked for “delete”. Sure enough I found it.

        <Association Name="FK_UserAddress_User">
          <End Role="ChatUser" Type="BAT.Data.Store.User" Multiplicity="1"">
            <OnDelete Action="Cascade" /">
          </End">

Eh ok… it’s there. Well after some searching I ran into this post. Basically what was happening is although that shows the OnDelete Action=”Cascade”, it’s still not everywhere it needs to be. Then it dawned on me that the way the .edmx file works is that pretty much everything has to be doubled in the file, once for the database and once for the actual class. What was missing was the class half. For some reason when adding Cascade to a foreign key and then updating the .edmx file, only the table part of the markup gets updated. Bummer. So, what to do? Kind the foreign key name in the file (FK_UserAddress_User for example) and do a search on it. You’ll find something like this:

     <Association Name="FK_UserAddress_User">
           <End Type="BAT.Data.ChatUser" Role="User" Multiplicity="1" />

Oooo right there is the problem. You see, if this were correctly done, it would have the action=”delete” added to it, just like the one in the SSDL area. So how do you fix this? Manually. Hooray.

     <Association Name="FK_UserAddress_User">
           <End Type="BAT.Data.ChatUser" Role="User" Multiplicity="1" >  //RIGHT HERE
             <OnDelete Action="Cascade"></OnDelete>  //RIGHT HERE
           </End>  //RIGHT HERE
     <End Type="BAT.Data.UserAddress" Role="UserAddress" Multiplicity="*" /></Association>

As you can see, it’s a simple change and you only have to do it to the object of Multiplicity=”1″, which of makes sense you wouldn’t want a user deleted if an address is. But it’s still annoying and a real pain if you have more than say one to fix.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...

I don’t like using the query syntax when it comes to Linq to AnythingButTheKitchenSink . Not sure why. Mostly, I guess, is that I seem to have a liking for Funcs and Actions to the point of stupidity and although you can work them into the query syntax, it just doesn’t look right.

Now with most of the Linq methods like Where or First, it’s simple once you understand lamdba expressions:

.SomeMethod(someField => someField.Property == value);

Now what about join?

JOINHELL

So inner selector with an outer selector and a selector selects a selecting selector. Right got it.

Well let’s try to break it down. First part is

this IEnumerable<TOuter>

So being that this is an extension method meaning this is the collection you are using this method on.

IEnumerable<TInner> inner

So second field must be the list you want to join to. Ok so far.

Func<TOuter, TKey> outerKeySelector

Now this is where it gets a little odd looking. We know we have Outer and Inner lists so there needs to be a way to join on something. Say Outer is User and Inner is UserAddress. Most likely you will have a UserID on both lists. If not, you do now. So basically what this part of the method is saying is “Give me the stupid key on the Outer (User) list that I should care about.”

, user => user.UserID,

Next part:

Func<TInner, TKey> innerKeySelector

Pretty much the same thing, except now it needs the key from the Innerlist (UserAddress):

, address => address.UserID,

Now for the fun part:

Func<TOuter, TInner, TResult> resultSelector

Sa…say what? Ok this may look weird at first but you’ll hate yourself for not seeing it. It’s just asking you what to select from the two lists as some kind of hybrid object. See, you have to remember that with these linq methods, each method will produce a list. You can’t just chain them together and have it remember every list you’ve made:

   user.Where(user => user.UserID > 1) // gives me a list of users
         .Select(user => new { user.UserName, user.UserAddress, user.UserID } 
         //Gives me new items with user name, address, and user id

From this simple method chain, the end list is NOT the same as the one you started with or the one produced by the where method.

The last part of the Join method needs you to tell it what it’s going to produce from this join. Now it probably could just guess and include both lists, but that could be seen as sloppy and ultimately this gives you the choice of what exactly needs to be taken after the join. So:

, (user, address) => new { user, address});

So in this case, the newly created and joined list with be a list of items that have a user and address attached to it much like if you had a list of:

class UserAddressHybrid()
{
    public User user { get; set; }
    public UserAddress userAddress { get; set; }
}

So in other words, WHAT DO YOU WANT YOUR RESULTS TO LOOK LIKE?

In full it would look something like:

user.Join(address => address.User.UserID,  //IEnumerable<TInner> inner
             user => user.UserID,  //Func<TOuter, TKey> outerKeySelector
             address => address.UserID,  //Func<TInner, TKey> innerKeySelector
             (user, address) => new { user, address});  //Func<TOuter, TInner, TResult> resultSelector

Not so hard anymore, is it?  You can start kicking yourself now.

Bookmark and Share
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...