EF Core Entity Circular Reference - asp.net

I am using C#.net and ef core. I have the models below. When I get my list of competitions, I want to only get my related user. However, I am getting the User and all the User's competitions. How can I achieve this? I had to do the following to get my list of competitions to show:
.AddJsonOptions(opt => opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore)
public partial class Competition
{
public int CompetitionId { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public partial class User
{
public int UserId { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public ICollection<Competition> Competitions { get; set; }
}
I have an api that uses entity framework to make calls to my database using the models describe above. The call in my api that causes the circular reference is the following:
[Produces("application/json")]
[Route("api/Competitions")]
public class CompetitionsController : Controller
{
private readonly ApplicationDBContext _context;
public CompetitionsController(ApplicationDBContext context)
{
_context = context;
}
// GET: api/Competitions
[HttpGet]
public IEnumerable<Competition> GetCompetitions()
{
//return _context.Competitions;
return _context.Competitions
.Include(u => u.User).ToList();
}
}
Below is my onmodelcreating code block in my ApplicationDBContext class:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Competition>(entity =>
{
entity.HasKey(e => e.CompetitionId);
entity.HasOne(d => d.User)
.WithMany(p => p.Competitions)
.HasForeignKey(d => d.UserId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Competitions_Users");
});
modelBuilder.Entity<User>(entity =>
{
entity.HasKey(e => e.UserId);
entity.HasIndex(e => e.UserName)
.HasName("UC_UserName")
.IsUnique();
entity.Property(e => e.Email)
.HasMaxLength(40)
.IsUnicode(false);
entity.Property(e => e.UserName)
.HasMaxLength(40)
.IsUnicode(false);
});
}

Old question, but in case someone still looking.
One solution is:
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

You should have ignored Competitions collection in user model while building.
modelBuilder.Entity<User>()
.Ignore(b => b.Competitions);

Related

No suitable constructor for entity type 'LineString'

Trying to migrate integration tests from the in-memory database to the PostGIS one, I always catch that exception when I call EnsureDeleted or EnsureCreated methods:
System.InvalidOperationException
No suitable constructor found for entity type 'LineString'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'points' in 'LineString(Coordinate[] points)'; cannot bind 'points', 'factory' in 'LineString(CoordinateSequence points, GeometryFactory factory)'.
With in-memory tests, all is working fine.
The only model with spatial data is this:
public class SurveilledArea
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
[Column(TypeName = "geometry (polygon)")]
public Polygon Polygon { get; set; }
public string AvigilonAlertId { get; set; }
public int MunicipalityId { get; set; }
public virtual Municipality Municipality { get; set; }
}
and my DbContext is this
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> dbContextOptions) : base(dbContextOptions)
{
}
public virtual DbSet<SurveilledArea> Areas { get; set; }
public virtual DbSet<Municipality> Municipalities { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<Device> Devices { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasPostgresExtension("postgis");
modelBuilder.Entity<SurveilledArea>()
.HasOne(p => p.Municipality)
.WithMany(p => p.SurveilledAreas)
.HasForeignKey(p => p.MunicipalityId)
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Report>()
.HasOne(p => p.Device)
.WithMany(p => p.Reports)
.HasForeignKey(p => new { p.DeviceType, p.DeviceAdId })
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.Entity<Municipality>()
.HasIndex(p => p.ShortCode)
.IsUnique();
modelBuilder.Entity<Device>()
.HasKey(device => new {device.Type, device.AdvertisingId});
base.OnModelCreating(modelBuilder);
}
}
What am I doing wrong?
I had a similar problem with a class that contained a Polygon property
public NetTopologySuite.Geometries.Polygon Polygon { get; set; }
You may need to add a package ref to Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite
Then in your data context builder implement something like this
public static MyDataContext CreateContext(string sqlConnectionStr) {
var optionsBuilder = new DbContextOptionsBuilder<MyDataContext>();
optionsBuilder.UseSqlServer(sqlConnectionStr, x => x.UseNetTopologySuite()
return new MyDataContext(optionsBuilder.Options);
}

One or more validation errors were detected during model generation Entity Framework

Hi I have a problem with relationship between my tables. When i try to get values from table i have an error:
OrderDetails_Order_Target_OrderDetails_Order_Source: : The number of
properties in the Dependent and Principal Roles in a relationship
constraint must be identical. OrderDetails_Processor_Source: :
Multiplicity is not valid in Role 'OrderDetails_Processor_Source' in
relationship 'OrderDetails_Processor'. Because the Dependent Role
refers to the key properties, the upper bound of the multiplicity of
the Dependent Role must be '1'.
OrderDetails_Processor_Target_OrderDetails_Processor_Source: : The
number of properties in the Dependent and Principal Roles in a
relationship constraint must be identical.
My classes and relationship look that:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Users>().HasKey(x => x.ID_User);
modelBuilder.Entity<Processor>().HasKey(x => x.Product_ID);
modelBuilder.Entity<GPU>().HasKey(x => x.Product_ID);
modelBuilder.Entity<Orders>().HasKey(x => new { x.Order_ID, x.User_ID });
modelBuilder.Entity<OrderDetails>().HasKey(x => new { x.Order_ID, x.Product_ID });
modelBuilder.Entity<OrderDetails>().HasRequired(x => x.Processor).WithMany(x => x.OrderDetails).HasForeignKey(x => new { x.Product_ID, x.Order_ID });
modelBuilder.Entity<OrderDetails>().HasRequired(x => x.GPU).WithMany(x => x.OrderDetails);
modelBuilder.Entity<OrderDetails>().HasRequired(x => x.Order).WithMany(x => x.OrderDetails);
modelBuilder.Entity<Orders>().HasMany(x => x.OrderDetails).WithRequired(x => x.Order);
modelBuilder.Entity<Orders>().HasRequired(x => x.User).WithMany(x => x.Orders);
modelBuilder.Entity<Processor>().HasMany(x => x.OrderDetails).WithRequired(x => x.Processor).HasForeignKey(x => new { x.Product_ID, x.Order_ID });
modelBuilder.Entity<GPU>().HasMany(x => x.OrderDetails).WithRequired(x => x.GPU);
modelBuilder.Entity<Users>().HasMany(x => x.Orders).WithRequired(x => x.User);
}
public class OrderDetails
{
public int Order_ID { get; set; }
public int Product_ID { get; set; }
public int Quantity { get; set; }
[ForeignKey(nameof(Product_ID))]
public Processor Processor { get; set; }
[ForeignKey(nameof(Product_ID))]
public GPU GPU { get; set; }
[ForeignKey(nameof(Order_ID))]
public Orders Order { get; set; }
}
public class Processor
{
[Key]
public int Product_ID { get; set; }
public string Title { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public ICollection<OrderDetails> OrderDetails { get; set; }
}
And here i get an error
public class EfProcessorContext : IProcessorRepository
{
private EfDbContext context = new EfDbContext();
public IEnumerable<Processor> Processors
{
get
{
return context.Processors.Include(x => x.OrderDetails);
}
}
}
What wrong I do?
The reason may be for the error is incorrectly configured relations in your model.
How to fix: The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical?
https://entityframework.net/knowledge-base/28699205/-the-number-of-properties-in-the-dependent-and-principal-roles-in-a-relationship-constraint-must-be-identical--issue-in-entity-framework
"The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical" issue in entity framework

EF table splitting with table AspNetUsers

I use two classes.
public partial class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<IntRole> Roles { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
public partial class ApplicationUser : IdentityUser<int, IntUserLogin, IntUserRole, IntUserClaim>
{
public virtual User User { get; set; }
}
I want to map both classes to table AspNetUsers.
I configured all fields in this table to make them optional.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>().HasOptional(a => a.User).WithMany().HasForeignKey(a => a.Id);
modelBuilder.Entity<ApplicationUser>().HasRequired(a => a.User).WithRequiredDependent(s => s.ApplicationUser);
modelBuilder.Entity<ApplicationUser>().Property(a => a.EmailConfirmed).IsOptional();
modelBuilder.Entity<ApplicationUser>().Property(a => a.PhoneNumber).IsOptional();
modelBuilder.Entity<ApplicationUser>().Property(a => a.PhoneNumberConfirmed).IsOptional();
modelBuilder.Entity<ApplicationUser>().Property(a => a.TwoFactorEnabled).IsOptional();
modelBuilder.Entity<ApplicationUser>().Property(a => a.LockoutEnabled).IsOptional();
modelBuilder.Entity<ApplicationUser>().Property(a => a.AccessFailedCount).IsOptional();
modelBuilder.Entity<ApplicationUser>().Property(a => a.UserName).IsOptional();
modelBuilder.Entity<User>().ToTable("AspNetUsers");
}
I make automatic migration and the result is successful.
When I want to add single User defined by class User in controller.
context.SpecialUser.Add(new Models.User { FirstName = "Halo", LastName = "Halo2" });
context.SaveChanges();
I got the following info.
Invalid data encountered. A required relationship is missing. Examine StateEntries to determine the source of the constraint violation.
What relationship should I define?
Result of InnerException.

EF 6.1.3 - Cannot insert duplicate key in object

I searched on site for solving my problem, but I still haven't solved it.
I have 2 entities:
public class Article
{
[Key]
public Guid ID { get; set; }
public Guid? ApprovedBy_ID { get; set; }
public Guid CreatedBy_ID { get; set; }
public virtual Profile ApprovedBy { get; set; }
public virtual Profile CreatedBy { get; set; }
//New guid for new article
public Article()
{
ID = Guid.NewGuid();
}
}
public class Profile
{
[Key]
public Guid ID { get; set; }
[Required]
[StringLength(100)]
public string FullName { get; set; }
public Profile()
{
ID = Guid.NewGuid();
}
}
And here is my insert-logic:
private readonly iContext context;
public ArticleLogic()
{
context = new iContext();
}
public IEnumerable<Article> GetAllArticle()
{
return context.Articles.Include("Categories").Include("Pictures").Include("ApprovedBy").Include("CreatedBy").Include("Template");
}
public Article AddArticle(Article article)
{
try
{
Profile pf = context.Profiles.First();
context.Profiles.Attach(pf);
Article art = new Article();
art.Title = article.Title;
art.Description = article.Description;
art.Content = article.Content;
art.Tag = article.Tag;
art.Template = article.Template;
//pf has ID = '0816f19c-31c1-4103-8f51-ba422beab1c0' (first row in database)
art.CreatedBy = pf;
art.CreatedBy_ID = pf.ID;
context.Articles.Add(art);
context.SaveChanges();
return article;
}
catch (Exception ex)
{
//But ex throw error duplicate ID = '7aa1d064-54ff-47b9-807d-db422fa71f8c' (second row in database)
Debug.WriteLine(ex.StackTrace);
throw ex;
}
}
DB Context:
public myContext()
: base("name=abc")
{
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ProxyCreationEnabled = false;
}
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<Template> Templates { get; set; }
public virtual DbSet<Article> Articles { get; set; }
public virtual DbSet<Picture> Pictures { get; set; }
public virtual DbSet<Profile> Profiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//One-to-many: Article - Picture (nullable)
modelBuilder.Entity<Picture>()
.HasOptional<Article>(c => c.Article)
.WithMany(p => p.Pictures)
.HasForeignKey(f => f.ArticleId);
////One-to-many: Role - Profile
modelBuilder.Entity<Profile>()
.HasRequired<Role>(i => i.Role)
.WithMany(i => i.Profiles)
.HasForeignKey(f => f.RoleID);
///Many-to-many: Article - Category
modelBuilder.Entity<Article>()
.HasMany(t => t.Categories)
.WithMany(t => t.Articles)
.Map(m => {
m.ToTable("ArticleCategories");
m.MapLeftKey("ArticleId");
m.MapRightKey("CategoryId");
});
//
modelBuilder.Entity<Article>()
.HasOptional(a => a.ApprovedBy)
.WithMany(a => a.ArticleApprovedBy)
.HasForeignKey(f=>f.ApprovedBy_ID)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Article>()
.HasRequired(a => a.CreatedBy)
.WithMany(a => a.ArticleCreatedBy)
.HasForeignKey(f => f.CreatedBy_ID)
.WillCascadeOnDelete(false);
base.OnModelCreating(modelBuilder);
}
I am using CodeFirst EF 6.1.3 and I am getting an error: Violation of PRIMARY KEY constraint 'PK_Profiles'. Cannot insert duplicate key in object 'dbo.Profiles' like this link Entity Framework Code First - Cannot insert duplicate key in object 'dbo.T_CRProviders'?
Can anyone help me? Thanks.
context thinks pf is new and should be inserted into the DB. Show the instantiation and configuration of context - do you have change tracking disabled?
You need to tell EF that a Profile can be referenced multiple times by Article:
modelBuilder.Entity<Article>()
.HasOptional(a=>a.ApprovedBy)
.WithMany()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Article>()
.HasOptional(a=>a.CreatedBy)
.WithMany()
.WillCascadeOnDelete(false);
The HasOptional could also be HasRequired if the property is mandatory (not null in the DB).
Adding WithMany is a key here if you want (as you do in your sample) be able to associate a profile to multiple properties of Article (and multiple Articles too).
PS: I wrote this code by memory, so something could need adjustment.
Your line:
context.Profiles.Attach(pf);
will attach the pf, however it is already tracked by EF. You just got it from the database. The pf will be reinserted by EF, and this fails. Just remove the line and you will be fine.
Add/Attach and Entity States

Validation failed for one or more entities. UserManager.AddToRole()

I'm developing a Web Api using ASP.NET MVC5 and I have successfully implemented a Custom IdentityUser.Like So
public partial class Authentication : IdentityUser
{
public Authentication()
{
this.LoginSessions = new List<LoginSession>();
}
[Required]
public string PersonId { get; set; }
public virtual Lecturer Lecturer { get; set; }
public virtual Student Student { get; set; }
public virtual ICollection<LoginSession> LoginSessions { get; set; }
}
with the following Maps
public class IdentityUserLoginConfiguration: EntityTypeConfiguration<IdentityUserLogin>
{
public IdentityUserLoginConfiguration()
{
HasKey(t => t.UserId);
}
}
public class IdentityRoleConfiguration : EntityTypeConfiguration<IdentityRole>
{
public IdentityRoleConfiguration()
{
HasKey(t => t.Id);
}
}
public class AuthenticationMap : EntityTypeConfiguration<Authentication>
{
public AuthenticationMap()
{
// Primary Key
this.HasKey(t => t.PersonId);
// Properties
this.Property(t => t.PersonId)
.IsRequired()
.HasMaxLength(14);
// Table & Column Mappings
this.ToTable("Authentication");
this.Property(t => t.PersonId).HasColumnName("PersonID");
// Relationships
this.HasOptional(t => t.Lecturer)
.WithOptionalPrincipal(t => t.Authentication);
this.HasOptional(t => t.Student)
.WithOptionalPrincipal(t => t.Authentication);
}
}
But now my problem is that when I'm adding a user to a Role Using the
UserManager.AddToRole()
method I get a DBValidationError
This is really worrying me and would like some help as soon as possible

Resources