How to use to use Entity Framework dynamic generated proxy?

B M-A 361 Reputation points
2022-08-18T15:12:43.207+00:00

Hello!

I have a WCF service that helps me to get some data from a database.
If I set ProxyCreationEnabled to false in DbContext, everything is works fine, but if I change ProxyCreationEnabled to true I get socket connection aborted error.
How to get data from Dynamic proxy?

Best regards,

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,415 questions
0 comments No comments
{count} votes

Accepted answer
  1. Michael Taylor 48,826 Reputation points
    2022-08-18T15:56:54.21+00:00

    There is something else going on here. Proxy creation is enabled by default and most people never really notice it. It forms the basis of lazy loading and without it lazy loading doesn't work. I suspect the problem is with the lazy loading side of the fence.

    With proxy creation enabled when you request data from the DB you get back a proxy object that wraps the actual type you are using. You can see this in the debugger. The proxy is responsible for updating the object based upon changes that occur in the system. The 2 most common changes are primary key updates and lazy loading in my experience. Take the following type:

       public class OrderLine  
       {  
          public int Id { get;set; }  
         
          public int ProductId { get; set; }  
          public virtual Product Product { get; set; }  
       }  
    

    If you create a new order line then the Id property is 0. When you add (and save) the data to the database then the DB generates the ID value. The proxy is responsible for retrieving that ID and setting Id automatically. Hence the following code works:

       var order = new OrderLine() { ProductId = 10 };  
       ...  
       var idNotSet = order.Id == 0;  
       _context.SaveChanges();  
       var idIsSet = order.Id != 0;  
    

    The other case of lazy loading is for loading children on demand. If lazy loading is enabled then the following works.

       var order = GetOrderLine(10);  
       var productMatches = order.ProductId == order.Product.Id;  
    

    Without lazy loading then you have to explicitly Include any child objects you want to reference. The proxy is responsible for handling this. If the proxy is disabled then lazy loading doesn't work irrelevant of whether you enabled it or not.

    So what is causing your error? I think the call stack should reveal that so you should catch the exception and look at the exception details (including inner exceptions). The message and stack trace will point to the issue. My running theory is that you're using lazy loading, you're DbContext was disposed and you then do something that triggers a lazy load of a child object. Normally I would expect an ObjectDisposedException but it depends on things that we cannot see from just your description.

    Ultimately lazy loading is more harmful then helpful so I would keep the proxy enabled and disable lazy loading, Include any child objects you care about. Alternatively ensure that all the data is loaded that you need before stepping outside the code that manages the lifetime of the DbContext. This, for example, will fail with lazy loading.

       public OrderLine GetOrderLine ( int id )  
       {  
          using (var context = GetDbContext())  
          {  
             return context.OrderLine.FirstOrDefault(x => x.Id == id);  
          };  
       }  
         
       var order = GetOrderLine(10);  
       var productId = order.Product.Id;  
    

1 additional answer

Sort by: Most helpful
  1. Jiayao Wu-MSFT 186 Reputation points Microsoft Vendor
    2022-08-19T08:07:59.377+00:00

    Hi @B M-A ,

    If possible, please provide the specific error information, so that you can locate the problem more quickly.

    Or you can try the following steps of lazy loading with Proxy:

    1. Make sure your navigation property are defined as "virtual".
    2. Install the Microsoft.EntityFrameworkCore.Proxies package.
    3. Enable it with a call to UseLazyLoadingProxies. protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder .UseLazyLoadingProxies() .UseSqlServer(myConnectionString);

    Or enable it when using AddDbContext:

    .AddDbContext<BloggingContext>(  
        b => b.UseLazyLoadingProxies()  
              .UseSqlServer(myConnectionString));  
    

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments