-1

I am creating a web application in C# using VS2012 to track contact attempts made to customers. I am saving the contact attempt, with 2 ref tables for contact attempt type, and contact attempt outcome, since these will always be fixed values. The problem I'm having is when I retrieve the App_ContactAttempt from the DB, it will bring back the App_ContactAttempt entity without the attached Ref_ContactOutcome and Ref_ContactType entities. I have lazy loading enabled and proxy creation enabled in the context file, and all ref table properties are set to virtual. But when I get an App_ContactAttempt from the db, there are not ref tables attached. Anyone got any ideas what I can do? If you need more information I can provide it.

UPDATE Right, I have a service setup to get the App_ContactAttempt, which looks like this:

    public App_ContactAttempt GetContactAttempt(int contactAttemptId)
    {
        using (var logger = new MethodLogger(contactAttemptId))
        {
            var contactAttempt = new App_ContactAttempt();
            try
            {
                contactAttempt = _unitOfWork.ContactAttempts.Get(contactAttemptId);
            }
            catch (Exception e)
            {
                logger.LogException(e.InnerException);
            }
            return contactAttempt;
        }
    }

When I use this service, I get back App_ContactAttempt when I call the service, but Ref_ContactType and Ref_ContactOutcome are null. But when I call to the db from within the controller using the db context like so:

    var db = new ParsDatabaseContext();

    var contactAttemptTest1 = _clientService.GetContactAttempt(contactAttempt.ContactAttemptId);

    var contactAttemptTest2 = db.App_ContactAttempt.Where(x => x.ContactAttemptId == contactAttempt.ContactAttemptId);

The contactAttemptTest1 returns the App_ContactAttempt with Ref_ContactType and Ref_ContactOutcome both being null. However, contactAttemptTest2 returns App_ContactAttempt with Ref_ContactType and Ref_ContactOutcome both being populated. Hope this helps narrow down my issue, because I haven't a clue..

UPDATE 2 Here are the context and classes if they help at all:

Context.cs

public partial class ParsDatabaseContext : DbContext
{
    public ParsDatabaseContext()
        : base("name=ParsDatabaseContext")
    {
        this.Configuration.LazyLoadingEnabled = true;
        this.Configuration.ProxyCreationEnabled = true;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public DbSet<App_Client> App_Client { get; set; }
    public DbSet<App_ContactAttempt> App_ContactAttempt { get; set; }
    public DbSet<Ref_ContactOutcome> Ref_ContactOutcome { get; set; }
    public DbSet<Ref_ContactType> Ref_ContactType { get; set; }

    public virtual ObjectResult<GetClient_Result> GetClient(Nullable<int> clientID)
    {
        var clientIDParameter = clientID.HasValue ?
            new ObjectParameter("ClientID", clientID) :
            new ObjectParameter("ClientID", typeof(int));

        return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<GetClient_Result>("GetClient", clientIDParameter);
    }
}

App_ContactAttempt.cs

public partial class App_ContactAttempt
{
    public int ContactAttemptId { get; set; }
    public int ClientId { get; set; }
    public Nullable<System.DateTime> ContactDate { get; set; }
    public Nullable<int> ContactType { get; set; }
    public Nullable<int> ContactOutcome { get; set; }
    public string Notes { get; set; }

    public virtual Ref_ContactOutcome Ref_ContactOutcome { get; set; }
    public virtual Ref_ContactType Ref_ContactType { get; set; }
}

Ref_ContactOutcome.cs

public partial class Ref_ContactOutcome
{
    public Ref_ContactOutcome()
    {
        this.App_ContactAttempt = new HashSet<App_ContactAttempt>();
    }

    public int ContactOutcomeId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<App_ContactAttempt> App_ContactAttempt { get; set; }
}

Ref_ContactType.cs

public partial class Ref_ContactType
{
    public Ref_ContactType()
    {
        this.App_ContactAttempt = new HashSet<App_ContactAttempt>();
    }

    public int ContactTypeId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<App_ContactAttempt> App_ContactAttempt { get; set; }
}
Tunaki
  • 132,869
  • 46
  • 340
  • 423
necrofish666
  • 75
  • 1
  • 7
  • 24
  • `there are not ref tables attached` - what do you mean? While debugging do you see the property `Ref_ContactOutcome` and it is null or what? – Vojtěch Dohnal May 17 '16 at 10:54
  • You either have to use the `Include` extension in your repository pattern or enabled lazy loading. – Igor May 17 '16 at 11:52
  • 1
    For lazy loading to work, the context *where you loaded the entity from* must be available (and not disposed) by the time you access the navigation property. Use eager loading (e.g., `Include`) if you want to work with very short lived contexts – Jcl May 17 '16 at 11:56
  • How do I know where the context is being displosed? I called the same service to get the ContactAttempt within the index method of the controller, and it brought back the associated Refs attached, but when I call the same service in another method on that controller, they aren't attached. Where would the context be getting disposed, and how do I stop it? – necrofish666 May 17 '16 at 12:20
  • What is `_unitOfWork` ? – Vojtěch Dohnal May 17 '16 at 12:24
  • http://www.c-sharpcorner.com/UploadFile/b1df45/unit-of-work-in-repository-pattern/ – necrofish666 May 17 '16 at 12:32
  • 2
    @necrofish666 Kindly do not vandalise your posts. – Praveen Kumar Purushothaman May 17 '16 at 13:20
  • Seems to me that you overcomplicate things for yourself with repository pattern, see this thread http://programmers.stackexchange.com/a/220126 – Vojtěch Dohnal May 17 '16 at 20:05
  • It does seem over-complicated to me too, but this is the method my workplace uses, so I have to use it :( – necrofish666 May 18 '16 at 10:55

3 Answers3

2

The problem is that lazy loading works only if the DBContext used to create the proxy class is available. In your case is the proxy detached because the DBContext used to crate the proxy object contactAttempt of type App_ContactAttempt has already been disposed.

Also make sure that:

dbContext.Configuration.ProxyCreationEnabled = true;

And you can check if the object is proxy

public static bool IsProxy(object type)
{
    return type != null && ObjectContext.GetObjectType(type.GetType()) != type.GetType();
}

https://msdn.microsoft.com/en-us/library/ee835846%28v=vs.100%29.aspx

See this answer to check if your proxy entity is attached to a DBContext.

You can attach existing detached entity to another existing context and make it lazy-loading again:

db.App_ContactAttempts.Attach(contactAttemptTest1);

If you have an entity that you know already exists in the database but which is not currently being tracked by the context then you can tell the context to track the entity using the Attach method on DbSet. The entity will be in the Unchanged state in the context.

See here.

So in your example:

using (var db = new ParsDatabaseContext())
{
   var contactAttemptTest1 = _clientService.GetContactAttempt(contactAttempt.ContactAttemptId);     
   db.App_ContactAttempts.Attach(contactAttemptTest1);    
   Debug.Print(contactAttemptTest1.Ref_ContactType.Description);
}

should work.

Community
  • 1
  • 1
Vojtěch Dohnal
  • 7,867
  • 3
  • 43
  • 105
0

Use includes.

For example:

var contactAttemps = db.App_ContactAttempts
                       .Includes("Ref_ContactOutcome")
                       .Includes("Ref_ContactTypes")
                       .ToList();
Barry O'Kane
  • 1,189
  • 7
  • 12
  • I'm using repository pattern to get entities from the db. I have a service setup, to which I pass the ContactAttemptId, which brings me back that record, but both Ref_ContactOutcome and Ref_ContactTypes are null. – necrofish666 May 17 '16 at 11:40
-1

Are you returning the entity itself or a DTO (data transfer object)?

if you are returning a DTO, ensure the mapping is properly done.

Post your entity object.

Sunny Okoro Awa
  • 523
  • 4
  • 9