c# - Self referencing loop detected (Solved 2-Ways)
Getting around C# self-referencing
loop exception
Sometimes we come across this
kind of error when building web apps. This kind of error occurs when we have
multiple navigational properties in the model and EF cannot parse the
relational objects. The best way to overcome this is to use the Newtonsoft
library to parse it to a string, use a DTO object or anonymous types to pass
the data required or set this in the Global.asax file to ignore reference loop
handling
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
= ReferenceLoopHandling.Ignore;
The Model class
If you have a product model
class that has a navigational property Category, it would be hard for EF to
parse the results of both properties to the view. Take a product class for example:
public class Product{
public int Id { get; set; }
public string Name{ get; set; }
public decimal Price{ get; set; }
public virtual Category Category { get; set; }
}
public int Id { get; set; }
public string Name{ get; set; }
public decimal Price{ get; set; }
public virtual Category Category { get; set; }
}
The product class has
another navigational class “Category” which has other properties.
public class Category{
public Category(){
Products = new HashSet<Product>();
}
public int Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<Product> Products { get; set; }
}
public class Category{
public Category(){
Products = new HashSet<Product>();
}
public int Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<Product> Products { get; set; }
}
If you try to use a
DbContext object to get the result for products in asp.net web api project, it
will throw an error message when there is data in both tables:
Var db = new DbContext();
return Ok(db.Products); //This would not work
return Ok(db.Products); //This would not work
Using Anonymous
Types
var products = db.Products.Select(p=>new{
p.Name,
p.Price,
CategoryName = p.Category.Name
});
p.Name,
p.Price,
CategoryName = p.Category.Name
});
return Ok(products);
Using Dto’s
Using Dto is simple, you just need to create a class and pass the required data.
Using Dto is simple, you just need to create a class and pass the required data.
Public class ProductDTO{
public string Name{get;set;}
public string Price{get;set;}
public string CategoryName{get;set;}
}
public string Name{get;set;}
public string Price{get;set;}
public string CategoryName{get;set;}
}
And do it this way:
var products = db.Products.Select(p=>new ProductDTO{
Name = p.Name,
Price = p.Price,
CategoryName = p.Category.Name
});
var products = db.Products.Select(p=>new ProductDTO{
Name = p.Name,
Price = p.Price,
CategoryName = p.Category.Name
});
return Ok(products);
But I prefer using
anonymous type because it just detect the name and you can also specify a
custom name. Using the second option has a drawback. It uses the properties
defined in the class to pass the data from the database but if there is a
property that is not assigned, it would return it empty in the output.
Comments
Post a Comment