Closed amukjee closed 1 year ago
@amukjee This works for me (full code below):
var property = modelBuilder
.Entity<MsiTdmdatamaster>()
.Property(e => e.DATAMASTER_DB_ID)
.ValueGeneratedOnAdd()
.HasComputedColumnSql(@"('DTM'+RIGHT('000000'+CONVERT([VARCHAR](6),[ID]),(6)))")
.Metadata;
property.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Key]
[Required]
public string DATAMASTER_DB_ID { get; set; }
info: 5/22/2023 11:00:02.783 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (28ms) [Parameters=[@p0='0', @p1='00:00:00', @p2='Y' (Nullable = false) (Size = 4000), @p3='0', @p4='00:00:00', @p5='638203464019392364' (Nullable = false) (Size = 4000), @p6='Z' (Nullable = false) (Size = 4000), @p7='False', @p8=NULL (Size = 4000)], CommandType='Text', CommandTimeout='
30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
INSERT INTO [dbo].[T_DM_DATAMASTER] ([DAILYCUTOFFDAYOFFSET], [DAILYCUTOFFTIME], [DAILYCYCLETIMEZONE], [DAILYKICKOFFDAYOFFSET], [DAILYKICKOFFTIME], [DATAMASTER_CODE], [DATAMASTER_LONGNAME], [IS_ENABLED], [NOTE])
OUTPUT INSERTED.[DATAMASTER_DB_ID], INSERTED.[ID]
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8);
ID = 7, DATAMASTER_DB_ID = DTM000007
info: 5/22/2023 11:00:02.999 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [t].[DATAMASTER_DB_ID], [t].[DAILYCUTOFFDAYOFFSET], [t].[DAILYCUTOFFTIME], [t].[DAILYCYCLETIMEZONE], [t].[DAILYKICKOFFDAYOFFSET], [t].[DAILYKICKOFFTIME], [t].[DATAMASTER_CODE], [t].[DATAMASTER_LONGNAME], [t].[ID], [t].[IS_ENABLED], [t].[NOTE]
FROM [dbo].[T_DM_DATAMASTER] AS [t]
ID = 4, DATAMASTER_DB_ID = DTM000004
ID = 6, DATAMASTER_DB_ID = DTM000006
ID = 7, DATAMASTER_DB_ID = DTM000007
#nullable disable
using (var context = new SomeDbContext())
{
var entity = new MsiTdmdatamaster()
{
DATAMASTER_CODE = DateTime.UtcNow.Ticks.ToString(),
DAILYCYCLETIMEZONE = "Y",
DATAMASTER_LONGNAME = "Z",
};
context.Add(entity);
context.SaveChanges();
Console.WriteLine($"ID = {entity.ID}, DATAMASTER_DB_ID = {entity.DATAMASTER_DB_ID}");
}
using (var context = new SomeDbContext())
{
foreach (var msiTdmdatamaster in context.Set<MsiTdmdatamaster>().ToList())
{
Console.WriteLine($"ID = {msiTdmdatamaster.ID}, DATAMASTER_DB_ID = {msiTdmdatamaster.DATAMASTER_DB_ID}");
}
}
public class SomeDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Database=AllTogetherNow")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var property = modelBuilder
.Entity<MsiTdmdatamaster>()
.Property(e => e.DATAMASTER_DB_ID)
.ValueGeneratedOnAdd()
.HasComputedColumnSql(@"('DTM'+RIGHT('000000'+CONVERT([VARCHAR](6),[ID]),(6)))")
.Metadata;
property.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
}
}
[Table("T_DM_DATAMASTER", Schema = "dbo")]
public partial class MsiTdmdatamaster
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Key]
[Required]
public string DATAMASTER_DB_ID { get; set; }
[Required]
public string DATAMASTER_CODE { get; set; }
[Required]
public short DAILYCUTOFFDAYOFFSET { get; set; }
[Required]
public TimeSpan DAILYCUTOFFTIME { get; set; }
[Required]
public short DAILYKICKOFFDAYOFFSET { get; set; }
[Required]
public TimeSpan DAILYKICKOFFTIME { get; set; }
[Required]
public string DAILYCYCLETIMEZONE { get; set; }
public bool IS_ENABLED { get; set; }
public string NOTE { get; set; }
[Required]
public string DATAMASTER_LONGNAME { get; set; }
}
Thank you @ajcvickers really appreciate your help.
So earlier as I mentioned in my code, I used: .Metadata.SetAfterSaveBehavior(Microsoft.EntityFrameworkCore.Metadata.PropertySaveBehavior.Throw);
The only thing I had to change to make (Add /Create ) it work is : (From AfterSave to BeforeSave) .Metadata.SetBeforeSaveBehavior(Microsoft.EntityFrameworkCore.Metadata.PropertySaveBehavior.ignore);
Its a Key column - So NULL entry not allowed, we must have a value before saving, that's I recon was the tweak and DB managed to calculate and generate the Value now.
Thank a lot again... I will proceed to mark the issue closed.
In My use case (DB [MS SQL 2019] First), we have a Table as below... We got an Identity Column ID but it is not the Primary Key, rather, there is [DATAMASTER_DB_ID] column which is Database derived/Calculated (based on ID column) column and this column is acting as Primary Key and it is having associated Foreign Key relationship with associated T_DM_DATADETAIL table.
Any suggestion how we can fit it with Entity Framework (using 7) for Model and CRUD page (Specially for ADD operation)?
What we tried:
Model:
Context / OnModelCreating
Irrespective of all trial and error so far, I only see - EF is continuously trying to Push a NULL value in DATAMASTER_DB_ID during insert and obviously Insert not working.
So far only workaround I could utilize is Not using EF and make insert via Stored Proc. But I am constantly doubting there must be some ways in EF to handle this situation. Any suggestion please?
Document Details
⚠ Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.