Tag-Modell
public class Tag : BaseModel
{
public string Name { get; set; }
public DateTime Creation { get; set; }
public int UsageCount { get; set; }
public int Likes { get; set; }
public int Dislikes { get; set; }
public bool IsActive { get; set; }
public override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Tag>(entity =>
{
entity.HasKey(t => t.Id);
entity.Property(t => t.Id).ValueGeneratedOnAdd();
entity.Property(t => t.Name).IsFixedLength(true).HasColumnType("VARCHAR(32)").HasMaxLength(32).IsRequired();
entity.Property(t => t.Creation).HasDefaultValue(DateTime.Now).IsRequired();
entity.Property(t => t.UsageCount).HasDefaultValue(0).IsRequired();
entity.Property(t => t.Likes).HasDefaultValue(0).IsRequired();
entity.Property(t => t.Dislikes).HasDefaultValue(0).IsRequired();
entity.Property(t => t.IsActive).HasDefaultValue(true).IsRequired();
});
}
}
DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var currentModel in Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsSubclassOf(typeof(BaseModel)) && !t.IsAbstract))
((BaseModel)Activator.CreateInstance(currentModel)).OnModelCreating(modelBuilder);
base.OnModelCreating(modelBuilder);
}
using (var context = new TagContext())
{
await context.Tags.InsertAsync(new Tag() { Name = "asdfasdfasdfasdfasdfadsfasdf;jklasdlasdfafsdlj;kafdsljkfsd;ljkf;sdlj;fkjlsd;jklfds" });
await context.SaveAsync();
}
Es spielt keine Rolle, wie ich die Spalte "Name" mit der Fluet-API definiere, die Einfügung schneidet die Eigenschaft nicht ab. Ich habe versucht:
entity.Property(t => t.Name).IsFixedLength(true).HasColumnType("VARCHAR(32)").HasMaxLength(32).IsRequired();
entity.Property(t => t.Name).IsFixedLength(true).HasMaxLength(32).IsRequired();
entity.Property(t => t.Name).HasMaxLength(32).IsRequired();
entity.Property(t => t.Name).IsFixedLength(true).HasColumnType("VARCHAR(32)").IsRequired();
entity.Property(t => t.Name).HasColumnType("VARCHAR(32)").IsRequired();
das modeldef wird einwandfrei aufgerufen.
Exception message: Exception thrown: 'Microsoft.EntityFrameworkCore.DbUpdateException' in System.Private.CoreLib.dll
Stack trace: at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__29.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__8.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__8.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__93.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__97.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.<ExecuteAsync>d__7`2.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__54.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at DBCT.Persistence.Repository.EntityFramework.EntityFrameworkUnitOfWork.<SaveAsync>d__5.MoveNext() in C:\Users\thoma\source\repos\DBCT\DBCT.Persistence\Repository\EntityFramework\EntityFrameworkUnitOfWork.cs:line 22
MySQL-Version:
Betriebssystem:
Pomelo.EntityFrameworkCore.MySql Version: 3.1.1
Microsoft.AspNetCore.App-Version: .NET Core 3.1
Informationen zur
Entity Framework führt keine Validierung der maximalen Länge durch, bevor Daten an den Anbieter übergeben werden. Es ist Sache des Anbieters oder Datenspeichers, gegebenenfalls zu validieren. Wenn Sie beispielsweise auf SQL Server abzielen, führt das Überschreiten der maximalen Länge zu einer Ausnahme, da der Datentyp der zugrunde liegenden Spalte nicht zulässt, dass überschüssige Daten gespeichert werden.
@Toemsel Beachten Sie zusätzlich zu den Aussagen von @mguinness , dass varchar(n)
keine feste Länge hat. Es ist ein Speichertyp mit variabler Länge. Das Äquivalent für die feste Länge beträgt jedoch char(n)
.
Eine Änderung von varchar(n)
in char(n)
macht jedoch keinen Unterschied in Bezug auf Ihre Ausnahme.
Dies ist beabsichtigt.
Wenn Sie Ihre Daten zuerst validieren möchten, finden Sie hier einige Artikel dazu:
Wenn Sie nur Zeichenfolgen abschneiden möchten, bevor Sie sie an die Datenbank senden, reicht es möglicherweise aus, einen Wertekonverter zu verwenden , der nur clientseitige Zeichenfolgen abschneidet:
`` `c #
Entität
.Eigenschaft (t => t.Name)
.HasMaxLength (32)
.Erforderlich()
.HasConversion (
v => v.Substring (0, Math.Min (v.Length, 32)),
v => v);
If you want to automate this, based on whether `MaxLength` has been defined or not, you can do that as well. Take a look at the following console app:
```c#
using System;
using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.Logging;
using Pomelo.EntityFrameworkCore.MySql.Storage;
namespace IssueConsoleTemplate
{
public class IceCream
{
public int IceCreamId { get; set; }
public string Name { get; set; }
}
public class Context : DbContext
{
public DbSet<IceCream> IceCreams { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseMySql(
"server=127.0.0.1;port=3306;user=root;password=;database=Issue1058",
b => b.ServerVersion(new ServerVersion("8.0.20-mysql")))
.UseLoggerFactory(
LoggerFactory.Create(
b => b
.AddConsole()
.AddFilter(level => level >= LogLevel.Information)))
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IceCream>(
entity =>
{
entity.Property(e => e.Name)
.HasMaxLength(5)
.IsRequired();
});
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
var maxLength = property.GetMaxLength().GetValueOrDefault();
if (maxLength > 0)
{
property.SetValueConverter(new ValueConverter<string,string>(
v => v.Substring(0, Math.Min(v.Length, maxLength)),
v => v));
}
}
}
}
}
internal class Program
{
private static void Main()
{
using (var context = new Context())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
}
using (var context = new Context())
{
context.IceCreams.Add(new IceCream {Name = "Vanilla"});
context.SaveChanges();
}
using (var context = new Context())
{
var iceCreams = context.IceCreams.ToList();
Debug.Assert(iceCreams.Count == 1);
Debug.Assert(iceCreams[0].Name == "Vanil");
}
}
}
}
@mguinness Oh, nun, ich dachte, fließend / Anmerkungen würden nicht nur für die Validierung / Erstellung / Migration existieren. Schön zu wissen und danke für den Hinweis.
@lauxjpn Danke, dass Sie mich über den Wertekonverter informiert haben. Das hilft sehr!
PS: Ja, Varchar ist in meinem Fall von 0 bis 32 dynamisch. Es war eine schlechte Wortwahl.
Danke Jungs!
Hilfreichster Kommentar
@Toemsel Beachten Sie zusätzlich zu den Aussagen von @mguinness , dass
varchar(n)
keine feste Länge hat. Es ist ein Speichertyp mit variabler Länge. Das Äquivalent für die feste Länge beträgt jedochchar(n)
.Eine Änderung von
varchar(n)
inchar(n)
macht jedoch keinen Unterschied in Bezug auf Ihre Ausnahme.Dies ist beabsichtigt.
Wenn Sie Ihre Daten zuerst validieren möchten, finden Sie hier einige Artikel dazu:
Wenn Sie nur Zeichenfolgen abschneiden möchten, bevor Sie sie an die Datenbank senden, reicht es möglicherweise aus, einen Wertekonverter zu verwenden , der nur clientseitige Zeichenfolgen abschneidet:
`` `c #
Entität
.Eigenschaft (t => t.Name)
.HasMaxLength (32)
.Erforderlich()
.HasConversion (
v => v.Substring (0, Math.Min (v.Length, 32)),
v => v);