System.ArgumentOutOfRangeException: Index was out of range. ef7 - c#

I'm getting a weird error when trying to add a project as a reference and using db
TitleAchievmentManager.cs
try
{
using var dbCustoms = new pCustoms.Database.DuckSoupExt();
var x = await dbCustoms.CustomName!.CountAsync();
}
catch (Exception ex)
{
Console.WriteLine($"{ex}");
}
Image Explanation
What's happening here is project pTitleAchievementManager trying to connect to the database from project pCustoms but it gives an exception
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'startIndex')
at System.String.LastIndexOf(Char value, Int32 startIndex, Int32 count)
at Microsoft.Data.Common.ADP.IsEndpoint(String dataSource, String prefix)
at Microsoft.Data.Common.ADP.IsAzureSynapseOnDemandEndpoint(String dataSource)
at Microsoft.Data.SqlClient.SqlConnection.CacheConnectionStringProperties()
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.CreateDbConnection()
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.get_DbConnection()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.CreateDbCommand(RelationalCommandParameterObject parameterObject, Guid commandId, DbCommandMethod commandMethod)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at pTitleAchievementManager.TitleAchievmentManager.FEATURE_CLIENT_ACHEIEVMENT_ACTIONS(Packet packet, ISession session, Object obj)
DuckSoupExt.cs from pCustoms
using API.ServiceFactory;
using API.Settings;
using Microsoft.EntityFrameworkCore;
using pCustoms.Database.Tables;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace pCustoms.Database
{
public partial class DuckSoupExt : DbContext
{
public DuckSoupExt()
{
}
public DuckSoupExt(DbContextOptions<DuckSoupExt> options)
: base(options)
{
}
public virtual DbSet<CustomIconDataTable> CustomIconData { get; set; }
public virtual DbSet<CustomIconTable> CustomIcon { get; set; }
public virtual DbSet<CustomIconVipDataTable> CustomIconVipData { get; set; }
public virtual DbSet<CustomIconVipTable> CustomIconVip { get; set; }
public virtual DbSet<CustomNameColorTable> CustomNameColor { get; set; }
public virtual DbSet<CustomNameTable> CustomName { get; set; }
public virtual DbSet<CustomTitleColorTable> CustomTitleColor { get; set; }
public virtual DbSet<CustomTitleTable> CustomTitle { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var Settings = ServiceFactory.Load<ISettingsManager>(typeof(ISettingsManager)).Settings;
optionsBuilder.UseSqlServer($"data source={Settings?.Address},{Settings?.Port};initial catalog={Settings?.ProxyDb};persist security info =True; User Id={Settings?.Username};Password={Settings?.Password};MultipleActiveResultSets=True;App=DuckSoupEntityFramework;Encrypt=False;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CustomIconDataTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomIconData");
entity.ToTable("CustomIconData");
entity.Property(e => e.path).HasMaxLength(255);
});
modelBuilder.Entity<CustomIconTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomIcon");
entity.ToTable("CustomIcon");
entity.Property(e => e.Charname).HasMaxLength(16);
});
modelBuilder.Entity<CustomIconVipDataTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomIconVipData");
entity.ToTable("CustomIconVipData");
entity.Property(e => e.path).HasMaxLength(255);
});
modelBuilder.Entity<CustomIconVipTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomIconVip");
entity.ToTable("CustomIconVip");
entity.Property(e => e.Charname).HasMaxLength(16);
});
modelBuilder.Entity<CustomNameColorTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomNameColor");
entity.ToTable("CustomNameColor");
entity.Property(e => e.Charname).HasMaxLength(16);
entity.Property(e => e.Color).HasMaxLength(30);
});
modelBuilder.Entity<CustomNameTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomName");
entity.ToTable("CustomName");
entity.Property(e => e.Charname).HasMaxLength(16);
entity.Property(e => e.Rank).HasMaxLength(80);
});
modelBuilder.Entity<CustomTitleColorTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomTitleColor");
entity.ToTable("CustomTitleColor");
entity.Property(e => e.Charname).HasMaxLength(16);
entity.Property(e => e.Color).HasMaxLength(30);
});
modelBuilder.Entity<CustomTitleTable>(entity =>
{
entity.HasKey(e => e.ID).HasName("PK_dbo.CustomTitle");
entity.ToTable("CustomTitle");
entity.Property(e => e.Charname).HasMaxLength(16);
entity.Property(e => e.Title).HasMaxLength(80);
});
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
The database is working fine within pCustoms but outside the project gives that error.

Related

Web API - EF Core 6.0 Create one to many relationship GET with nested relationship

Using EF Power tools I have the following classes created:
Category.cs
public partial class Category
{
public Category()
{
Folders = new HashSet<Folder>();
Reports = new HashSet<Report>();
}
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string CategoryDescription { get; set; }
public string ImagePath { get; set; }
public virtual ICollection<Folder> Folders { get; set; }
public virtual ICollection<Report> Reports { get; set; }
}
Folder.cs
public partial class Folder
{
public Folder()
{
Reports = new HashSet<Report>();
}
public int FolderId { get; set; }
public string FolderName { get; set; }
public int CategoryId { get; set; }
public string FolderDescription { get; set; }
public string FolderImagePath { get; set; }
public virtual Category Category { get; set; }
public virtual ICollection<Report> Reports { get; set; }
}
The underlying tables are linked one to many with Categoryid.
I believe the dbContext.cs was generated correctly based on the table schema.
dbContext.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Category>(entity =>
{
entity.HasKey(e => e.CategoryId)
.IsClustered(false);
entity.ToTable("Category");
entity.Property(e => e.CategoryId)
.ValueGeneratedNever()
.HasColumnName("CategoryID");
entity.Property(e => e.CategoryDescription)
.HasMaxLength(300)
.IsUnicode(false);
entity.Property(e => e.CategoryName)
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.ImagePath)
.HasMaxLength(250)
.IsUnicode(false);
} );
modelBuilder.Entity<Folder>(entity =>
{
entity.HasKey(e => e.FolderId)
.IsClustered(false);
entity.ToTable("Folder");
entity.Property(e => e.FolderId)
.ValueGeneratedNever()
.HasColumnName("FolderID");
entity.Property(e => e.CategoryId).HasColumnName("CategoryID");
entity.Property(e => e.FolderDescription)
.HasMaxLength(300)
.IsUnicode(false);
entity.Property(e => e.FolderImagePath)
.HasMaxLength(250)
.IsUnicode(false);
entity.Property(e => e.FolderName)
.HasMaxLength(100)
.IsUnicode(false);
entity.HasOne(d => d.Category)
.WithMany(p => p.Folders)
.HasForeignKey(d => d.CategoryId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_Folder_01");
});
OnModelCreatingPartial(modelBuilder);
}
I then have the following in the controller:
[HttpGet]
public async Task<ActionResult<IEnumerable<Category>>> GetCategories()
{
return await _context.Categories.ToListAsync();
}
When I run the WebAPI I see the following:
[
{
"categoryId": 1,
"categoryName": "Some Name",
"folders": [],
"reports": []
},
{
"categoryId": 2,
"categoryName": "Another Name",
"folders": [],
"reports": []
},
]
How do I get the related data to populate in the folders array?
I also tried this:
public async Task<ActionResult<IEnumerable<Category>>> GetCategories()
{
var query = (from r in _context.Categories
from bu in _context.Folders
where r.CategoryId == bu.CategoryId
select r
).ToListAsync();
return await query;
I suspect that you application has the loading of relationship to lazy loading.
This means that every relation on the model specified wont be loaded until you ask to specifically see them.
In this specific case you could tell your application to load all the data you need in one go.
[HttpGet]
public async Task<ActionResult<IEnumerable<Category>>> GetCategories()
{
// note the .Include will tell you application context to load the relation Folders by default
return await _context.Categories.Include(x => x.Folders).ToListAsync();
}
Here is more information if you want to learn all the way's you could load your relationships by default

EF Core ToList DBNull to int?

The EF core Firebird provider does not convert DBNull to nullable types. When I have an entity with a nullable int? property and I simply get all entries in a table using await this._dbContext.EmpLevels.ToListAsync() I get the exception that I cannot cast a DBNull to Int32 as stated here: https://learn.microsoft.com/en-us/dotnet/api/system.dbnull.system-iconvertible-toint32?view=net-6.0. Theoretically, this makes sense because an int cannot represent null but it's a nullable property.
I found a lot of questions with the same problem, but not related to Firebird, where they have access to the readers or data tables, but in my case, I don't have them. So how can I parse null values from firebird into a nullable int?
EDIT:
But when I add HasConversion it works fine although I just pass the type of the property:
Before: entity.Property(e => e.CertId).HasColumnName("CERT_ID");
After: entity.Property(e => e.CertId).HasColumnName("CERT_ID").HasConversion<int?>();
The problem is that I don't have to add it to the property CertId. I first added HasConversion to the wrong property by accident and this worked too (property: CapId) although it's not even a nullable int because CertId is the only nullable.
EDIT 2:
Entity:
public partial class EmpLevel
{
public int EmpId { get; set; } = default!;
public int CapId { get; set; } = default!;
public DateTime StartDate { get; set; } = default!;
public int LevelId { get; set; } = default!;
public int? CertId { get; set; }
public virtual Certificate? Cert { get; set; }
public virtual EmpsCap EmpsCap { get; set; } = default!;
public virtual CapLevel Level { get; set; } = default!;
}
DbContext:
public class CapsDbContext : DbContext {
...
public virtual DbSet<EmpLevel> EmpLevels { get; set; }
...
public CapsDbContext(DbContextOptions<CapsDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
...
modelBuilder.Entity<EmpLevel>(entity => {
entity.HasKey(e => new { e.EmpId, e.CapId, e.StartDate });
entity.ToTable("EMP_LEVELS");
entity.HasIndex(e => e.CertId);
entity.HasIndex(e => new { e.CapId, e.EmpId });
entity.HasIndex(e => e.LevelId);
entity.HasIndex(e => new { e.StartDate, e.CapId, e.EmpId });
entity.HasIndex(e => new { e.StartDate, e.CapId, e.EmpId })
.IsUnique();
entity.Property(e => e.EmpId).HasColumnName("EMP_ID");
entity.Property(e => e.CapId).HasColumnName("CAP_ID");
entity.Property(e => e.StartDate)
.HasColumnType("DATE")
.HasColumnName("START_DATE");
entity.Property(e => e.CertId).HasColumnName("CERT_ID").HasConversion<int?>();
entity.Property(e => e.LevelId).HasColumnName("LEVEL_ID");
entity.HasOne(d => d.Cert)
.WithMany(p => p.EmpLevels)
.HasForeignKey(d => d.CertId)
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("FK_CERT_EMPLEVEL");
entity.HasOne(d => d.Level)
.WithMany(p => p.EmpLevels)
.HasForeignKey(d => d.LevelId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_LEVEL_EMPLEVEL");
entity.HasOne(d => d.EmpsCap)
.WithMany(p => p.EmpLevels)
.HasForeignKey(d => new { d.EmpId, d.CapId })
.HasConstraintName("FK_EMPSCAPS_EMPLEVEL");
});
...
}
}
Exception:
System.InvalidCastException: Object cannot be cast from DBNull to other types.
at System.DBNull.System.IConvertible.ToInt32(IFormatProvider provider)
at System.Convert.ToInt32(Object value, IFormatProvider provider)
at FirebirdSql.Data.Common.DbValue.GetInt32()
at FirebirdSql.Data.FirebirdClient.FbDataReader.GetInt32(Int32 I)
at lambda_method1001(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
System.InvalidCastException: Object cannot be cast from DBNull to other types.
at System.DBNull.System.IConvertible.ToInt32(IFormatProvider provider)
at System.Convert.ToInt32(Object value, IFormatProvider provider)
at FirebirdSql.Data.Common.DbValue.GetInt32()
at FirebirdSql.Data.FirebirdClient.FbDataReader.GetInt32(Int32 I)
at lambda_method1001(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()

C# NPGSQL Connection is Busy

I've got the following problem:
I'm using NPGSQL for the Connection to the Database. Furthermore I'm using Entity Framework Core.
This is how my Context looks like:
using System.IO;
using DatabaseLibrary.Models.Discount;
using DatabaseLibrary.Models.Gender;
using DatabaseLibrary.Models.Ranks;
using DatabaseLibrary.Models.Employee;
using DatabaseLibrary.Models.Items;
using DatabaseLibrary.Models.Settings;
using DatabaseLibrary.Models.Transaction;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace DatabaseLibrary
{
// ReSharper disable once InconsistentNaming
public class PGSQLConnectionManager : DbContext
{
//Variables
private IConfiguration Configuration { get; }
//public PGSQLConnectionManager(DbContextOptions<PGSQLConnectionManager> options) : base(options)
//{
// Configuration = (new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.Development.json").Build());
//}
public PGSQLConnectionManager()
{
Configuration = (new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.Development.json").Build());
}
public PGSQLConnectionManager(IConfiguration configuration)
{
Configuration = configuration;
}
//Database
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseNpgsql(
Configuration["ConnectionStrings:PGSQLConnectionManager"]
);
//Model Sets
public DbSet<Gender> Gender { get; set; }
public DbSet<Gender2Employee> Gender2Employee { get; set; }
public DbSet<EmployeeRank> EmployeeRank { get; set; }
public DbSet<Employee> Employee { get; set; }
public DbSet<Item> Item { get; set; }
public DbSet<ItemType> ItemType { get; set; }
public DbSet<ItemType2Item> ItemType2Items { get; set; }
public DbSet<EmployeeRank2Employee> EmployeeRank2Employees { get; set; }
public DbSet<Transaction> Transactions { get; set; }
public DbSet<Transaction2Items> Transaction2Items { get; set; }
public DbSet<TransactionNonItem> TransactionNonItem { get; set; }
public DbSet<TaxSettings> TaxSettings { get; set; }
public DbSet<Discount> Discount { get; set; }
public DbSet<Transaction2Discount> Transaction2Discount { get; set; }
public DbSet<EmployeeRank2AspRole> EmployeeRank2AspRoles { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Gender>().ToTable("Gender");
modelBuilder.Entity<Gender2Employee>().ToTable("Gender2Employee");
modelBuilder.Entity<EmployeeRank>().ToTable("EmployeeRank");
modelBuilder.Entity<Employee>().ToTable("Employee");
modelBuilder.Entity<EmployeeRank2Employee>().ToTable("EmployeeRank2Employee");
modelBuilder.Entity<Item>().ToTable("Item");
modelBuilder.Entity<ItemType>().ToTable("ItemType");
modelBuilder.Entity<ItemType2Item>().ToTable("ItemType2Item");
modelBuilder.Entity<Transaction>().ToTable("Transaction");
modelBuilder.Entity<Transaction2Items>().ToTable("Transaction2Items");
modelBuilder.Entity<TransactionNonItem>().ToTable("TransactionNonItem");
modelBuilder.Entity<TaxSettings>().ToTable("TaxSettings");
modelBuilder.Entity<Discount>().ToTable("Discount");
modelBuilder.Entity<Transaction2Discount>().ToTable("Transaction2Discount");
modelBuilder.Entity<EmployeeRank2AspRole>().ToTable("EmployeeRank2AspRole");
/*
* Primary Key auto increment
*/
modelBuilder.Entity<Gender>()
.Property(g => g.GenderId)
.UseIdentityColumn();
modelBuilder.Entity<Gender2Employee>()
.Property(g => g.Gender2EmployeeId)
.UseIdentityColumn();
modelBuilder.Entity<Item>()
.Property(i => i.ItemId)
.UseIdentityColumn();
modelBuilder.Entity<ItemType>()
.Property(it => it.ItemTypeId)
.UseIdentityColumn();
modelBuilder.Entity<ItemType2Item>()
.Property(iti => iti.ItemType2ItemId)
.UseIdentityColumn();
modelBuilder.Entity<EmployeeRank>()
.Property(er => er.EmployeeRankId)
.UseIdentityColumn();
modelBuilder.Entity<EmployeeRank2Employee>()
.Property(ere => ere.EmployeeRank2EmployeeId)
.UseIdentityColumn();
modelBuilder.Entity<Transaction>()
.Property(t => t.TransactionId)
.UseIdentityColumn();
modelBuilder.Entity<Transaction2Items>()
.Property(ti => ti.Transaction2ItemsId)
.UseIdentityColumn();
modelBuilder.Entity<TransactionNonItem>()
.Property(tni => tni.TransactionId)
.UseIdentityColumn();
modelBuilder.Entity<TaxSettings>()
.Property(ts => ts.TaxSettingsId)
.UseIdentityColumn();
modelBuilder.Entity<Discount>()
.Property(d => d.DiscountId)
.UseIdentityColumn();
modelBuilder.Entity<Transaction2Discount>()
.Property(t2d => t2d.Transaction2DiscountId)
.UseIdentityColumn();
modelBuilder.Entity<EmployeeRank2AspRole>()
.Property(e2a => e2a.EmployeeRank2AspRoleId)
.UseIdentityColumn();
/*
* Relations
*/
//Gender
modelBuilder.Entity<Gender2Employee>()
.HasOne<Employee>()
.WithMany()
.HasForeignKey(e => e.EmployeeId)
.HasPrincipalKey(e => e.EmployeeId);
modelBuilder.Entity<Gender2Employee>()
.HasOne<Gender>()
.WithMany()
.HasForeignKey(g => g.GenderId)
.HasPrincipalKey(g => g.GenderId);
//item
modelBuilder.Entity<ItemType2Item>()
.HasOne<Item>()
.WithMany()
.HasForeignKey(i => i.ItemId)
.HasPrincipalKey(i => i.ItemId);
modelBuilder.Entity<ItemType2Item>()
.HasOne<ItemType>()
.WithMany()
.HasForeignKey(i => i.ItemTypeId)
.HasPrincipalKey(i => i.ItemTypeId);
//transaction
//transaction2items
modelBuilder.Entity<Transaction2Items>()
.HasOne<Transaction>()
.WithMany()
.HasForeignKey(t => t.TransactionId)
.HasPrincipalKey(t => t.TransactionId);
modelBuilder.Entity<Transaction2Items>()
.HasOne<Item>()
.WithMany()
.HasForeignKey(i => i.ItemId)
.HasPrincipalKey(i => i.ItemId);
//transaction2discount
modelBuilder.Entity<Transaction2Discount>()
.HasOne<Transaction>()
.WithMany()
.HasForeignKey(t => t.TransactionId)
.HasPrincipalKey(t => t.TransactionId);
modelBuilder.Entity<Transaction2Discount>()
.HasOne<Discount>()
.WithMany()
.HasForeignKey(d => d.DiscountId)
.HasPrincipalKey(d => d.DiscountId);
//employeerank2asproleid
modelBuilder.Entity<EmployeeRank2AspRole>()
.HasOne<EmployeeRank>()
.WithMany()
.HasForeignKey(er => er.EmployeeRankId)
.HasPrincipalKey(er => er.EmployeeRankId);
}
}
}
In my Startup.cs I'm adding the context to the dependency injection like this:
//Database initialization
services.AddDbContext<PGSQLConnectionManager>(options =>
options.UseNpgsql(Configuration.GetConnectionString("PGSQLConnectionManager")));
services.AddDatabaseDeveloperPageExceptionFilter();
Now since my latest additional query I was using the Context like this:
In any .razor file I'm injecting the PGSQLConnectionManager:
#inject PGSQLConnectionManager Context
And later on in the .razor file in the #code part, I use the injected Context like this:
GetEmployee getAllEmployees = new GetEmployee(Context);
And every Class that needs a database connection is getting initialized like this:
public class GetEmployee
{
//Variables
private readonly PGSQLConnectionManager _connectionManager;
public GetEmployee(PGSQLConnectionManager context)
{
_connectionManager = context;
}
public List<Employee> GetAllEmployees()
{
try
{
//query all employees
List<Employee> allEmployees = _connectionManager.Employee.AsQueryable().ToList();
return allEmployees;
}
catch (Exception e)
{
#I know this is bad, but reporting is to come
return null;
}
}
}
And now, that I've done this like, >20 times I get an error: Connection is Busy
I tried using a static class and reference the PGSQLConnectionManager in there once, but then everytime I try to get the Context I get an error, that the Object has been disposed??? and can't get accessed anymore.
As far as I know, objects do not get disposed if they are in a static class.
I couldn't find where the database gets disposed in the static class thing.
So far, I think I'm using EntityFramework or the NPGSQL wrong. But I cannot find a good example, that represents my case.
Thanks ahead for any help

The instance of entity type cannot be tracked because another instance... EF Core error when updating db

Service:
public Cart AddProductToCart(Product product, Cart cart)
{
var productExist = _dbContexet.CartProduct.Where(cp => cp.ProductId == product.Id).FirstOrDefault();
var quantityOfCart = _dbContexet.CartProduct.Where(cp => cp.CartId == cart.Id).FirstOrDefault().Quantity;
CartProduct cartProduct = new CartProduct();
cartProduct.CartId = cart.Id;
cartProduct.ProductId = product.Id;
if (productExist != null)
{
cartProduct.Quantity = quantityOfCart + 1;
_dbContexet.Attach(cartProduct).State = EntityState.Modified;
}
else
{
cartProduct.Cart = cart;
cartProduct.Product = product;
_dbContexet.CartProduct.Add(cartProduct);
}
_dbContexet.SaveChanges();
return cart;
}
Full error:
InvalidOperationException: The instance of entity type 'CartProduct'
cannot be tracked because another instance with the same key value for
{'CartId', 'ProductId'} is already being tracked. When attaching
existing entities, ensure that only one entity instance with a given
key value is attached. Consider using
'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the
conflicting key values.
I have many to many and table CartProduct I want to check if product exist and only update quantity if it exist but I get this error?
Eddit:
Product:
public partial class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public decimal CostToMake { get; set; }
public decimal FinalPrice { get; set; }
//public int? OrderId { get; set; }
public virtual Order Order { get; set; }
public List<CartProduct> CartProduct { get; set; }
}
Cart:
public class Cart
{
public int Id { get; set; }
public int ProductCount { get; set; }
public AppUser User { get; set; }
public List<CartProduct> CartProduct { get; set; }
}
CartProduct:
public class CartProduct
{
public int CartId { get; set; }
public int ProductId { get; set; }
public Cart Cart { get; set; }
public Product Product { get; set; }
public int Quantity { get; set; }
}
FluentAPI:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasAnnotation("Relational:Collation", "Cyrillic_General_CI_AS");
modelBuilder.Entity<Day>(entity =>
{
entity.Property(e => e.Date).HasColumnType("date");
entity.Property(e => e.MostCommonCategory)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.MostCommonProduct)
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.TotalMade).HasColumnType("decimal(18, 3)");
entity.Property(e => e.TotalSpent).HasColumnType("decimal(18, 3)");
});
modelBuilder.Entity<Order>(entity =>
{
entity.Property(e => e.Date).HasColumnType("date");
entity.Property(e => e.Status)
.IsRequired()
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.Name).HasMaxLength(100);
entity.Property(e => e.Address).HasMaxLength(150);
entity.Property(e => e.PhoneNumber).HasMaxLength(20);
});
modelBuilder.Entity<Product>(entity =>
{
entity.HasIndex(e => e.OrderId, "IX_Products_OrderId");
entity.Property(e => e.Category)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.CostToMake).HasColumnType("decimal(18, 3)");
entity.Property(e => e.FinalPrice).HasColumnType("decimal(18, 3)");
entity.Property(e => e.Name)
.IsRequired()
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.Price).HasColumnType("decimal(18, 3)");
entity.HasOne(d => d.Order)
.WithMany(p => p.Products)
.HasForeignKey(d => d.OrderId);
});
modelBuilder.Entity<Cart>(entity => {
entity.HasKey(e => e.Id);
entity.HasOne(e => e.User)
.WithOne(e => e.Cart)
.HasForeignKey<AppUser>(e => e.CartId);
});
modelBuilder.Entity<CartProduct>()
.HasKey(e => new { e.CartId, e.ProductId });
modelBuilder.Entity<CartProduct>()
.HasOne(t => t.Cart)
.WithMany(t => t.CartProduct)
.HasForeignKey(t => t.ProductId);
modelBuilder.Entity<CartProduct>()
.HasOne(t => t.Product)
.WithMany(t => t.CartProduct)
.HasForeignKey(t => t.CartId);
OnModelCreatingPartial(modelBuilder);
}
You can perform some actions but in a different way, using EF features.
public Cart AddProductToCart(Product product, Cart cart)
{
var product = _dbContexet.Product.Where(cp => cp.ProductId == product.Id).Include(x => x.CartProduct).FirstOrDefault();
var quantityOfCart = _dbContexet.CartProduct.Where(cp => cp.CartId == cart.Id).FirstOrDefault().Quantity;
var cartProduct = product.CartProduct.Where(x=>x.CartId == cart.id).FirstOrDefault();
if (cartProduct != null)
{
cartProduct.Quantity = quantityOfCart + 1;
}
else
{
product.CartProduct.Add(new CartProduct { CartId = cart.id });
}
//_dbContexet.Update(product) if you are using QueryTrackingBehavior.NoTracking
_dbContexet.SaveChanges();
return cart;
}
Your error is because :
cartProduct.CartId = cart.Id;
cartProduct.ProductId = product.Id;
in reallity is the same as:
cartProduct.Cart = cart;
cartProduct.Product = product;
so just remove from your code:
cartProduct.Cart = cart;
cartProduct.Product = product;

Entity type 'Microsoft.AspNetCore.Identity.IdentityRole' is in shadow-state

I've been playing around with this quickstart example & have been trying to see how far I can customise the database (I have an existing database I've been half-trying to replicate).
I've managed to trigger the exception below and am having trouble fixing it, partially because I don't understand what the message is telling me.
InvalidOperationException: Entity type
'Microsoft.AspNetCore.Identity.IdentityRole' is in shadow-state. A
valid model requires all entity types to have corresponding CLR type.
My ApplicationDbContext is as follows:
using IdentityServerWithAspIdAndEF.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
namespace IdentityServerWithAspIdAndEF.Data
{
public class ApplicationDbContext : IdentityDbContext<User, Role, int>
{
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> Options
) : base(Options) { }
protected override void OnModelCreating(ModelBuilder ModelBuilder)
{
base.OnModelCreating(ModelBuilder);
// Customisations
// "IdentityServer4AspNetIdentity.Models.ApplicationUser"
ModelBuilder.Entity<User>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("AccountId")
.ValueGeneratedOnAdd();
B.Property<string>("ConcurrencyStamp")
.HasMaxLength(512)
.IsConcurrencyToken();
B.Property<string>("Email")
.HasMaxLength(512)
.IsRequired();
B.Property<bool>("EmailConfirmed")
.ValueGeneratedOnAdd();
B.Property<string>("NormalisedEmail")
.HasMaxLength(512)
.IsRequired();
B.Property<string>("NormalisedUserName")
.HasMaxLength(256)
.IsRequired();
B.Property<string>("PasswordHash");
B.Property<string>("SecurityStamp")
.IsRequired();
B.Property<bool>("TwoFactorEnabled")
.ValueGeneratedOnAdd();
B.Property<string>("UserName")
.HasMaxLength(256)
.IsRequired();
B.Property<DateTime>("Registered")
.ValueGeneratedOnAdd();
B.Property<DateTime>("LastVisit")
.IsRequired();
B.HasKey("AccountId");
B.HasIndex("NormalisedEmail")
.HasName("IX_Users_NormalisedEmail");
B.HasIndex("NormalisedUserName")
.IsUnique()
.HasName("IX_Users_NormalisedUserName");
B.ToTable("Users");
});
// "Microsoft.AspNetCore.Identity.IdentityRole"
ModelBuilder.Entity<Role>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("RoleId")
.ValueGeneratedOnAdd();
B.Property<string>("ConcurrencyStamp")
.HasMaxLength(512)
.IsConcurrencyToken();
B.Property<string>("Name")
.HasMaxLength(256);
B.Property<string>("NormalisedName")
.HasMaxLength(256);
B.HasKey(P => P.Id);
B.HasIndex("NormalisedName")
.IsUnique()
.HasName("IX_Roles_NormalisedName");
B.ToTable("Roles");
});
// "Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>"
ModelBuilder.Entity<RoleClaim>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("ClaimId")
.ValueGeneratedOnAdd();
B.Property<string>("ClaimType")
.HasMaxLength(128);
B.Property<string>("ClaimValue")
.HasMaxLength(128);
B.Property<int>("RoleId")
.IsRequired();
B.HasIndex(P => P.RoleId)
.HasName("IX_RoleClaims_RoleId");
B.HasOne(D => D.Claim)
.WithMany()
.HasForeignKey(P => P.RoleId)
.OnDelete(DeleteBehavior.Cascade);
B.ToTable("RoleClaims");
});
// "Microsoft.AspNetCore.Identity.IdentityUserClaim<string>"
ModelBuilder.Entity<UserClaim>(B =>
{
B.Property<int>(P => P.Id)
.HasColumnName("ClaimId")
.ValueGeneratedOnAdd();
B.Property<string>("ClaimType")
.HasMaxLength(128);
B.Property<string>("ClaimValue")
.HasMaxLength(128);
B.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();
B.HasIndex("AccountId")
.HasName("IX_UserClaims_AccountId");
B.HasOne(D => D.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);
B.ToTable("UserClaims");
});
// "Microsoft.AspNetCore.Identity.IdentityUserLogin<string>"
ModelBuilder.Entity<Login>(B =>
{
B.Property<int>(P => P.UserId)
.HasColumnName("LoginId")
.ValueGeneratedOnAdd();
B.Property<string>("LoginProvider")
.HasMaxLength(450)
.IsRequired();
B.Property<string>("ProviderKey")
.HasMaxLength(450)
.IsRequired();
B.Property<string>("ProviderDisplayName");
B.Property<int>("AccountId")
.IsRequired();
B.HasIndex("LoginProvider")
.HasName("IX_Logins_LoginProvider");
B.HasIndex("ProviderKey")
.HasName("IX_Logins_ProviderKey");
B.HasIndex("AccountId")
.HasName("IX_Logins_AccountId");
B.HasOne(D => D.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);
B.ToTable("Logins");
});
// "Microsoft.AspNetCore.Identity.IdentityUserRole<string>"
ModelBuilder.Entity<UserRole>(B =>
{
B.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();
B.Property<int>("RoleId")
.IsRequired();
B.HasIndex("AccountId")
.HasName("IX_RoleMap_AccountId");
B.HasIndex("RoleId")
.HasName("IX_RoleMap_RoleId");
B.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
B.HasOne(P => P.Account)
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade);
B.ToTable("RoleMap");
});
// "Microsoft.AspNetCore.Identity.IdentityUserToken<string>"
ModelBuilder.Entity<Token>(B =>
{
B.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();
B.Property<string>("LoginProvider")
.HasMaxLength(128)
.IsRequired();
B.Property<string>("Name")
.HasMaxLength(64);
B.Property<string>("Value");
B.HasOne(P => P.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);
B.ToTable("UserTokens");
});
// Non-identity extras
/* snipped */
}
}
}
The entities that correspond with these DbSets are as follows:
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
namespace IdentityServerWithAspIdAndEF.Models
{
public class User : IdentityUser<int>
{
public int AccountId
{
get => base.Id;
set => base.Id = value;
}
public string NormalisedEmail
{
get => base.NormalizedEmail;
set => base.NormalizedEmail = value;
}
public string NormalisedUserName
{
get => base.NormalizedUserName;
set => base.NormalizedUserName = value;
}
public DateTime Registered { get; set; }
public DateTime LastVisit { get; set; }
public AccountDetail UserDetails { get; set; }
public AccountLockout Lockout { get; set; }
public PasswordReset PasswordResetRequested { get; set; }
public Concierge ConciergeAccountFlag { get; set; }
public NotValidated AccountValidatation { get; set; }
public ICollection<UserRole> AssignedRoles { get; set; }
public ICollection<UserClaim> ClaimsCollection { get; set; }
public ICollection<Login> Logins { get; set; }
public ICollection<LoginAttempt> LoginAttempts { get; set; }
public ICollection<Token> TokenCollection { get; set; }
public new int Id => throw new NotImplementedException();
public override string NormalizedEmail => throw new NotImplementedException();
public override string NormalizedUserName => throw new NotImplementedException();
}
public class Role : IdentityRole<int>
{
public int RoleId
{
get => base.Id;
set => base.Id = value;
}
public string NormalisedName
{
get => base.NormalizedName;
set => base.NormalizedName = value;
}
public ICollection<RoleClaim> ClaimsCollection { get; set; }
private new int Id => throw new NotImplementedException();
private new int NormalizedName => throw new NotImplementedException();
}
public class RoleClaim : IdentityRoleClaim<int>
{
public int ClaimId
{
get => base.Id;
set => base.Id = value;
}
public Role Claim { get; set; }
private new int Id => throw new NotImplementedException();
}
public class UserClaim : IdentityUserClaim<int>
{
public int ClaimId
{
get => base.Id;
set => base.Id = value;
}
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}
public User Account { get; set; }
private new int Id => throw new NotImplementedException();
private new int UserId => throw new NotImplementedException();
}
public class Login : IdentityUserLogin<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}
public User Account { get; set; }
private new int UserId => throw new NotImplementedException();
}
public class UserRole : IdentityUserRole<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}
public User Account { get; set; }
private new int UserId => throw new NotImplementedException();
}
public class Token : IdentityUserToken<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}
private new int UserId => throw new NotImplementedException();
public User Account { get; set; }
}
}
I have read the posts "What does it mean for an entity type to be in “shadow state”?" and "Entity type 'type' is in shadow-state. A valid model requires all entity types to have corresponding CLR type"
Judging from the documentation I think that I may have missed, or mis-referenced, the Role entity somewhere, but it's not clear to me where.
Thanks in advance!
Edit:
Re-reading the shadow property documentation, the line "By convention, shadow properties are only created when a relationship is discovered but no foreign key property is found in the dependent entity class. In this case, a shadow foreign key property will be introduced." seems to support that I've mucked up the entity.
I've tried to rule out a property name mismatch by changing all property references in the Role and RoleClaim ModelBuilder entity declarations to expressions, to the following to see if hard referencing will help:
// "Microsoft.AspNetCore.Identity.IdentityRole"
ModelBuilder.Entity<Role>(B =>
{
B.Property(P => P.RoleId)
.ValueGeneratedOnAdd();
B.Property(E => E.ConcurrencyStamp)
.HasMaxLength(512)
.IsConcurrencyToken();
B.Property(E => E.Name)
.HasMaxLength(256);
B.Property(E => E.NormalisedName)
.HasMaxLength(256);
B.HasKey(P => P.Id);
B.HasIndex(E => E.NormalisedName)
.IsUnique()
.HasName("IX_Roles_NormalisedName");
B.ToTable("Roles");
});
// "Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>"
ModelBuilder.Entity<RoleClaim>(B =>
{
B.Property(P => P.ClaimId)
.ValueGeneratedOnAdd();
B.Property(E => E.ClaimType)
.HasMaxLength(128);
B.Property(E => E.ClaimValue)
.HasMaxLength(128);
B.Property(E => E.RoleId)
.IsRequired();
B.HasIndex(P => P.RoleId)
.HasName("IX_RoleClaims_RoleId");
B.HasOne(D => D.Claim)
.WithMany()
.HasForeignKey(P => P.RoleId)
.OnDelete(DeleteBehavior.Cascade);
B.ToTable("RoleClaims");
});
But no luck so far.
It appears as though I'd made several mistakes, the most pertinent is that I hadn't actually provided code for my UserRole object within the ApplicationDbContext sample; this is actually where the error was originating...
The code still referenced the original IdentityRole model:
// "Microsoft.AspNetCore.Identity.IdentityUserRole<string>"
ModelBuilder.Entity<UserRole>(E =>
{
E.Property<int>(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();
E.Property<int>("RoleId")
.IsRequired();
E.HasIndex("AccountId")
.HasName("IX_RoleMap_AccountId");
E.HasIndex("RoleId")
.HasName("IX_RoleMap_RoleId");
E.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") // Argh!
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
E.HasOne(P => P.Account)
.WithMany()
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade);
E.ToTable("RoleMap");
});
This was updated to reference properties, instead of using magic strings to specify the field names; which highlighted the error I'd made.
// "Microsoft.AspNetCore.Identity.IdentityUserRole<string>"
ModelBuilder.Entity<UserRole>(E =>
{
E.Property(P => P.UserId)
.HasColumnName("AccountId")
.IsRequired();
E.Property(P => P.RoleId)
.IsRequired();
E.HasIndex(P => P.AccountId)
.HasName("IX_RoleMap_AccountId");
E.HasIndex(P => P.RoleId)
.HasName("IX_RoleMap_RoleId");
E.HasOne(P => P.Role) // 'UserRole' does not contain a definition for 'Role'
.WithMany()
.HasForeignKey(P => P.RoleId)
.OnDelete(DeleteBehavior.Cascade);
E.HasOne(P => P.Account)
.WithMany()
.HasForeignKey(P => P.AccountId)
.OnDelete(DeleteBehavior.Cascade);
E.ToTable("RoleMap");
});
And:
public class UserRole : IdentityUserRole<int>
{
public int AccountId
{
get => base.UserId;
set => base.UserId = value;
}
public User Account { get; set; }
public Role Role { get; set; } // Addition
}
At this point the exception informing me that IdentityRole was operating in a shadow-state seems to have disappeared and been replaced by others.
Additionally (and I'm not 100% sure that this contributed to the exception I was seeing) I had misconfigured my RoleStore within Startup->ConfigureServices.
Services.AddIdentity<User, Role>()
.AddUserStore<CustomerUserStore>()
.AddUserManager<CustomerManager>()
.AddRoleStore<Role>() // Should have been CustomerRoleStore
.AddRoleManager<RoleManager>()
.AddSignInManager<CustomerSignInManager>()
.AddDefaultTokenProviders();
CustomerRoleStore also required an override to allow IdentityServer to understand the roles after my customisations, which looks as so:
public class CustomerRoleStore
: RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>
{
public CustomerRoleStore(
ApplicationDbContext context,
IdentityErrorDescriber describer = null
) : base(
context,
describer
)
{ }
protected override RoleClaim CreateRoleClaim(Role role, Claim claim)
{
return new RoleClaim
{
RoleId = role.RoleId,
ClaimType = claim.Type,
ClaimValue = claim.Value
};
}
}

Categories