0

i am using entity framework 5 using database first in my project. i believe there is some problem in lazy loading of values in foreign key virtual field and i have tried every possible way but i am not able to resolve the issue so far.

Here are the details:

i have a CustomerDiscountCardController index method as follows:

public ActionResult Index(String searchTerm = null, int page = 1)
        {
            var model = CustomerDiscountCardPagedList(searchTerm, page);


            ViewBag.CustomerID = new SelectList(db.Customers.OrderBy(c => c.FirstName), "CustomerID", "FirstName");
            if (Request.IsAjaxRequest())
            {
                return PartialView("_CustomerDiscountCard", model);
            }
            return View(model);
        }

        private IPagedList<CustomerDiscountCard> CustomerDiscountCardPagedList(String searchTerm, int page)
        {
            var model = db.CustomerDiscountCards.Include( d => d.DiscountCard).
                OrderBy(c => c.DiscountCard.CardName).
                Where(c => (c.DiscountCard.CardName.Contains(searchTerm))).
                Select(c => new
                {
                    DiscountCardID = c.DiscountCardID,
                    CustomerID = c.CustomerID,
                    IssueDate = c.IssueDate,
                    ExpiryDate = c.ExpiryDate,
                    CustomerDiscountCardID = c.CustomerDiscountCardID
                }
                ).ToList().Select(c => new CustomerDiscountCard
                {
                    DiscountCardID = c.DiscountCardID,
                    CustomerID = c.CustomerID,
                    IssueDate = c.IssueDate,
                    ExpiryDate = c.ExpiryDate,
                    CustomerDiscountCardID = c.CustomerDiscountCardID

                }).ToPagedList(page, 4);
            return model;
        }

My data context class looks as below:

    public OnlineFoodOrderingEntities2()
        : base("name=OnlineFoodOrderingEntities2")
    {
        this.Configuration.LazyLoadingEnabled = true;
        this.Configuration.ProxyCreationEnabled = true;
    }
    //Entities class code....

}

My auto generated CustomerDiscountCard class looks like below:

public partial class CustomerDiscountCard
{
    public int CustomerDiscountCardID { get; set; }
    public Nullable<int> DiscountCardID { get; set; }
    public Nullable<int> CustomerID { get; set; }
    public Nullable<System.DateTime> IssueDate { get; set; }
    public Nullable<System.DateTime> ExpiryDate { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual DiscountCard DiscountCard { get; set; }
}

Now the problem is when my index method is called on ajax request returning the partial layout of _CustomerDiscountCard

the code of layout is as below:

@using PagedList;
@using PagedList.Mvc;
@using OnlineFoodOrderingMVC.Models;
@model IPagedList<CustomerDiscountCard>

<div id="targetCustomerDiscountCardList">

    <div class="pagedList" data-ofo-target="#targetCustomerDiscountCardList">

        @Html.PagedListPager(Model, page => Url.Action("Index", "CustomerDiscountCard", new { page }),
        PagedListRenderOptions.MinimalWithItemCountText)
    </div>
    <div style="clear:both"></div>
    <div>
        <table class="entity_record_table">
            <tr class="entity_record_table_header">
                <th class="entity_record_table_header_item_text">
                    CustomerDiscountCards
                </th>
                <th class="entity_record_table_header_link_text">
                    Edit
                </th>
                <th class="entity_record_table_header_link_text">
                    View
                </th>
                <th class="entity_record_table_header_link_text">
                    Delete
                </th>
            </tr>
            @{
                String[] rowDisplay = { "entity_record_row_display1", "entity_record_row_display2" };
                String currentClass = "entity_record_row_display1";
                int count = 0;
            }

            @foreach (var item in Model)
            {

                count++;
                currentClass = rowDisplay[count % 2];

                <tr class="@(currentClass)">
                    <td class="entity_record_table_item">
                        @Html.DisplayFor(modelItem => item.DiscountCard.CardName)
                    </td>
                    <td class="entity_record_table_link">
                        @Ajax.ActionLink(" ", "Edit", new { id = item.CustomerDiscountCardID },
                        new AjaxOptions
                             {
                                 HttpMethod = "get",
                                 InsertionMode = InsertionMode.Replace,
                                 UpdateTargetId = "targetDiv"
                             }
                        , new { @class = "entity_record_edit" })
                    </td>
                    <td class="entity_record_table_link">
                        @Ajax.ActionLink(" ", "Details", new { id = item.CustomerDiscountCardID },
                              new AjaxOptions
                                {
                                    HttpMethod = "get",
                                    InsertionMode = InsertionMode.Replace,
                                    UpdateTargetId = "targetCustomerDiscountCardList"
                                }
                        , new { @class = "entity_record_view" })
                    </td>
                    <td class="entity_record_table_link">
                        @Ajax.ActionLink(" ", "Delete", new { id = item.CustomerDiscountCardID },
                              new AjaxOptions
                                {
                                    HttpMethod = "get",
                                    InsertionMode = InsertionMode.Replace,
                                    UpdateTargetId = "targetCustomerDiscountCardList"
                                }
                        , new { @class = "entity_record_delete" })
                    </td>
                </tr>

            }

        </table>
    </div>

</div>

so when razor engine is rendering this partial view of mine and executing this following command

item.DiscountCard.CardName

i am getting DicountCard to be null, i am not able to understand what is causing this to be null can any one please help me with this one. Thanks a lot in advance.

  • For one in your razor @Html.DisplayFor you are doing `@Html.DisplayFor(modelItem => item.DiscountCard.CardName)` Notice that you are calling for the model as **modelItem**, but than you do **item** change **item** to **modelItem** – dklingman May 21 '14 at 11:26
  • i just added snapshot of a code so that viewer will understand what i am trying to achieve if you want will post full code of razor view which is as follows – user3649270 May 21 '14 at 11:52
  • @dklingman: the OP is doing that in a `foreach` block. The correct expression *is* `modelItem => item`. – Chris Pratt May 21 '14 at 13:39

1 Answers1

1

The problem is that DiscountCard really is null. When you fetch the items, you're using Select to create a new class out of a subset of values:

            Select(c => new
            {
                DiscountCardID = c.DiscountCardID,
                CustomerID = c.CustomerID,
                IssueDate = c.IssueDate,
                ExpiryDate = c.ExpiryDate,
                CustomerDiscountCardID = c.CustomerDiscountCardID
            }
            ).ToList().Select(c => new CustomerDiscountCard
            {
                DiscountCardID = c.DiscountCardID,
                CustomerID = c.CustomerID,
                IssueDate = c.IssueDate,
                ExpiryDate = c.ExpiryDate,
                CustomerDiscountCardID = c.CustomerDiscountCardID

            })

First, what you're doing is repetitive. There's no reason to select to an anonymous object, cast to a list and then select to a real class instance with the same data. Just select directly to the class instance, i.e.:

            Select(c => new CustomerDiscountCard
            {
                DiscountCardID = c.DiscountCardID,
                CustomerID = c.CustomerID,
                IssueDate = c.IssueDate,
                ExpiryDate = c.ExpiryDate,
                CustomerDiscountCardID = c.CustomerDiscountCardID

            })

Second, you never set a value for DiscountCard, only DiscountCardId. When you create a new instance like this, it is not attached to your context, and has no way of fetching or retrieving this related value. Which brings us to...

Third, why are you selecting anything in the first place? You start off with an enumerable of CustomerDiscountCard and then select into an enumerable of new CustomerDiscountCard instances. The only thing this does is break the attachment of these items to your context, effectively killing any ability to lazy load anything.

UPDATE

Just change it to:

var model = db.CustomerDiscountCards.Include( d => d.DiscountCard).
            OrderBy(c => c.DiscountCard.CardName).
            Where(c => (c.DiscountCard.CardName.Contains(searchTerm))).
            ToPagedList(page, 4);
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • then please can you tell me a way that how can i possibly achieve it with paged list ? – user3649270 May 21 '14 at 14:04
  • Thanks a lot for your answer , but what you posted before giving the update i tried workaround for what you posted and i ended up with something similar as yours and it solved my problem still million thanks to you, and shame that i cannot post answer till 8 hours as i am a new member – user3649270 May 21 '14 at 14:26