Danza
7월 3, 2022, 9:52오전
1
sql 직접 실행, DbSet.FromSqlRaw(), SqlConnection.Execute()는 문제 없지만, SaveChanges할 땐 예외가 발생합니다.
sql문
INSERT INTO dbo.SubCategory (Name, MainCategoryName) VALUES ('subName1', 'mainName')
DbSet.Add() 호출
context.SubCategories.Add(new SubCategory()
{
MainCategoryName = "mainName",
Name = "subName2"
});
context.SaveChanges();
소스 코드 보면서 확인하고 있는데 스택의 sqlDataReader.GetInt32(int i)이 코드 의 184줄에서 예외 발생, dbDataReader에서 값을 구하고 int로 cast하는 중 예외가 발생하는 것으로 보이는데, 이걸 외부에서 해결 가능할까요?
메시지:
Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while saving the entity changes. See the inner exception for details.
---- System.InvalidCastException : Unable to cast object of type ‘System.String’ to type ‘System.Int32’.
스택 추적:
AffectedCountModificationCommandBatch.Consume(RelationalDataReader reader)
ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
BatchExecutor.Execute(IEnumerable1 commandBatches, IRelationalConnection connection) RelationalDatabase.SaveChanges(IList
1 entries)
StateManager.SaveChanges(IList1 entriesToSave) StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess) <>c.<SaveChanges>b__104_0(DbContext _, ValueTuple
2 t)
SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func3 operation, Func
3 verifySucceeded)
StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
DbContext.SaveChanges()
MockDb.ctor() 줄 72
TestReviewService.ReviewService_GetReviewInfo() 줄 80
----- Inner Stack Trace -----
SqlBuffer.get_Int32()
SqlDataReader.GetInt32(Int32 i)
lambda_method417(Closure , DbDataReader )
AffectedCountModificationCommandBatch.ConsumeResultSetWithPropagation(Int32 commandIndex, RelationalDataReader reader)
AffectedCountModificationCommandBatch.Consume(RelationalDataReader reader)
2개의 좋아요
현재 엔터티 구조와 데이터베이스 구조가 맞지 않는것 같습니다. 확인해보시겠어요? 환경정보를 공유 주시면 좀 더 정확한 도움이 될 것 같습니다.
3개의 좋아요
Danza
7월 3, 2022, 10:24오전
3
DB는 local sql server입니다
Model
public sealed class SubCategory
{
public string Name { get; set; }
public string MainCategoryName { get; set; }
public int ReviewCount { get; set; }
public MainCategory MainCategory { get; set; }
public List<ReviewItem> ReviewItems { get; set; }
}
Entity
modelBuilder.Entity<SubCategory>(build =>
{
build.ToTable("SubCategory");
build.HasKey(s => s.Name);
build.HasOne(s => s.MainCategory).WithMany(m => m.SubCategories).HasForeignKey(m => m.MainCategoryName).IsRequired();
build.Property(s => s.Name).HasMaxLength(30).HasColumnType("nvarchar(30)");
build.Property(s => s.ReviewCount).HasDefaultValue(0).IsRequired();
});
Table
CREATE TABLE [dbo].[SubCategory] (
[Name] NVARCHAR (30) NOT NULL,
[MainCategoryName] NVARCHAR (30) NOT NULL,
[ReviewCount] INT DEFAULT ((0)) NOT NULL,
CONSTRAINT [PK_SubCategory] PRIMARY KEY CLUSTERED ([Name] ASC),
CONSTRAINT [FK_SubCategory_MainCategory_MainCategoryName] FOREIGN KEY ([MainCategoryName]) REFERENCES [dbo].[MainCategory] ([Name]) ON DELETE CASCADE
);
몇시간동안 뚫어져라 봐도 원인을 모르겠네요;;
2개의 좋아요
아래 코드처럼 작성했을 때 문제없이 동작하는 것을 보니 MainCategory
나 ReviewItem
타입에 원인이 있을 수도 있겠네요.
저 두 모델에서 데이터 타입이 올바른지 확인이 필요합니다.
/*
* https://forum.dotnetdev.kr/t/dbset-save-invalidcastexception/3996
*/
using var context = new TestContext();
context.Database.EnsureCreated();
context.Database.Migrate();
context.SubCategories.Add(new SubCategory()
{
MainCategoryName = "mainName",
Name = "subName2"
});
context.SaveChanges();
public class TestContext : DbContext
{
public DbSet<SubCategory> SubCategories { get; set; } = default!;
public string DbPath { get; }
public TestContext()
{
var folder = Environment.SpecialFolder.UserProfile;
var path = Environment.GetFolderPath(folder);
DbPath = Path.Join(path, "Downloads", "categories.db");
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={DbPath}");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<SubCategory>(build =>
{
build.ToTable("SubCategory");
build.HasKey(s => s.Name);
//build.HasOne(s => s.MainCategory).WithMany(m => m.SubCategories).HasForeignKey(m => m.MainCategoryName).IsRequired();
build.Property(s => s.Name).HasMaxLength(30).HasColumnType("nvarchar(30)");
build.Property(s => s.ReviewCount).HasDefaultValue(0).IsRequired();
});
}
}
public sealed class SubCategory
{
public string Name { get; set; }
public string MainCategoryName { get; set; }
public int ReviewCount { get; set; }
// public MainCategory MainCategory { get; set; }
// public List<ReviewItem> ReviewItems { get; set; }
}
6개의 좋아요
Danza
7월 3, 2022, 2:21오후
5
insert trigger 지우니까 작동했습니다.
게다가 원래 트리거가 작동을 안했네요;;
일단 해결 방법은 알았는데 이유는 여전히 모르는 상태…
더 알아봐야 할 것 같습니다…
CREATE OR ALTER TRIGGER [dbo].[TR_SubCategory_AfterInsert_DML]
ON [dbo].[SubCategory]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE @name nvarchar(30) SELECT MainCategoryName FROM inserted
UPDATE dbo.MainCategory SET SubCategoryCount += 1 WHERE [Name] = @name
END
GO
4개의 좋아요