使用实体框架将更改保存到SQL Server数据库时,一个或多个实体的验证失败

如何解决使用实体框架将更改保存到SQL Server数据库时,一个或多个实体的验证失败

|| 我想将我的编辑保存到数据库,并且在ASP.NET MVC 3 / C#中使用实体框架优先代码,但出现错误。在我的Event类中,我有DateTime和TimeSpan数据类型,但是在我的数据库中,我分别有Date和time。这可能是原因吗?将更改保存到数据库之前,如何在代码中强制转换为适当的数据类型。
public class Event
{
    public int EventId { get; set; }
    public int CategoryId { get; set; }
    public int PlaceId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public DateTime EventDate { get; set; }
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }
    public string Description { get; set; }
    public string EventPlaceUrl { get; set; }
    public Category Category { get; set; }
    public Place Place { get; set; }
}
控制器>>>>中的方法storeDB.SaveChanges()中的问题;
// POST: /EventManager/Edit/386        
[HttpPost]
public ActionResult Edit(int id,FormCollection collection)
{
    var theEvent = storeDB.Events.Find(id);

    if (TryUpdateModel(theEvent))
    {
        storeDB.SaveChanges();
        return RedirectToAction(\"Index\");
    }
    else
    {
        ViewBag.Categories = storeDB.Categories.OrderBy(g => g.Name).ToList();
        ViewBag.Places = storeDB.Places.OrderBy(a => a.Name).ToList();
        return View(theEvent);
    }
}
public class EventCalendarEntities : DbContext
{
    public DbSet<Event> Events { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<Place> Places { get; set; } 
}
SQL Server 2008 R2数据库/ T-SQL
EventDate (Datatype = date)  
StartTime (Datatype = time)  
EndTime (Datatype = time)  
Http表格
EventDate (Datatype = DateTime) e.g. 4/8/2011 12:00:00 AM  
StartTime (Datatype = Timespan/time not sure) e.g. 08:30:00  
EndTime (Datatype = Timespan/time not sure) e.g. 09:00:00  
\'/ \'应用程序中的服务器错误。 一个或多个实体的验证失败。有关更多详细信息,请参见\'EntityValidationErrors \'属性。 说明:执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪,以获取有关错误及其在代码中起源的更多信息。 异常详细信息:System.Data.Entity.Validation.DbEntityValidationException:对一个或多个实体的验证失败。有关更多详细信息,请参见\'EntityValidationErrors \'属性。 源错误:
Line 75:             if (TryUpdateModel(theEvent))
Line 76:             {
Line 77:                 storeDB.SaveChanges();
Line 78:                 return RedirectToAction(\"Index\");
Line 79:             }
源文件:C:\\ sep \\ MvcEventCalendar \\ MvcEventCalendar \\ Controllers \\ EventManagerController.cs行:77 堆栈跟踪: [DbEntityValidationException:对一个或多个实体的验证失败。有关更多详细信息,请参见\'EntityValidationErrors \'属性。]     

解决方法

        您可以使用以下代码从ѭ6中提取所有信息(您需要在
using
列表中添加名称空间:
System.Data.Entity.Validation
System.Diagnostics
):
catch (DbEntityValidationException dbEx)
{
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            Trace.TraceInformation(\"Property: {0} Error: {1}\",validationError.PropertyName,validationError.ErrorMessage);
        }
    }
}
    ,        无需更改代码: 在
catch {...}
块中处于调试模式时,打开\“ QuickWatch \”窗口(Ctrl + Alt + Q)并粘贴在其​​中:
((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
要么:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
如果您不在try / catch中,或者没有访问异常对象的权限。 这将允许您深入到“ 14”树。这是我发现的能够立即洞悉这些错误的最简单方法。     ,        如果您的类具有相同的属性名称,则这是Praveen答案的一个小扩展:
 catch (DbEntityValidationException dbEx)
 {
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
       foreach (var validationError in validationErrors.ValidationErrors)
       {
          Trace.TraceInformation(
                \"Class: {0},Property: {1},Error: {2}\",validationErrors.Entry.Entity.GetType().FullName,validationError.ErrorMessage);
       }
    }
 }
    ,        作为对Praveen和Tony的改进,我使用了覆盖:
public partial class MyDatabaseEntities : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Trace.TraceInformation(\"Class: {0},validationError.ErrorMessage);
                }
            }

            throw;  // You can also choose to handle the exception here...
        }
    }
}
    ,        此实现将实体异常包装为带有详细文本的异常。 它处理
DbEntityValidationException
DbUpdateException
datetime2
范围错误(MS SQL),并在消息中包含无效实体的键(在一次
SaveChanges
调用中保存多个实体时很有用)。 首先,在DbContext类中重写ѭ20:
public class AppDbContext : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException dbEntityValidationException)
        {
            throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
        }
        catch (DbUpdateException dbUpdateException)
        {
            throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
        }
    }   

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
    {
        try
        {
            return await base.SaveChangesAsync(cancellationToken);
        }
        catch (DbEntityValidationException dbEntityValidationException)
        {
            throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
        }
        catch (DbUpdateException dbUpdateException)
        {
            throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
        }
    }
ExceptionHelper类:
public class ExceptionHelper
{
    public static Exception CreateFromEntityValidation(DbEntityValidationException ex)
    {
        return new Exception(GetDbEntityValidationMessage(ex),ex);
    }

    public static string GetDbEntityValidationMessage(DbEntityValidationException ex)
    {
        // Retrieve the error messages as a list of strings.
        var errorMessages = ex.EntityValidationErrors
            .SelectMany(x => x.ValidationErrors)
            .Select(x => x.ErrorMessage);

        // Join the list to a single string.
        var fullErrorMessage = string.Join(\"; \",errorMessages);

        // Combine the original exception message with the new one.
        var exceptionMessage = string.Concat(ex.Message,\" The validation errors are: \",fullErrorMessage);
        return exceptionMessage;
    }

    public static IEnumerable<Exception> GetInners(Exception ex)
    {
        for (Exception e = ex; e != null; e = e.InnerException)
            yield return e;
    }

    public static Exception CreateFromDbUpdateException(DbUpdateException dbUpdateException)
    {
        var inner = GetInners(dbUpdateException).Last();
        string message = \"\";
        int i = 1;
        foreach (var entry in dbUpdateException.Entries)
        {
            var entry1 = entry;
            var obj = entry1.CurrentValues.ToObject();
            var type = obj.GetType();
            var propertyNames = entry1.CurrentValues.PropertyNames.Where(x => inner.Message.Contains(x)).ToList();
            // check MS SQL datetime2 error
            if (inner.Message.Contains(\"datetime2\"))
            {
                var propertyNames2 = from x in type.GetProperties()
                                        where x.PropertyType == typeof(DateTime) ||
                                            x.PropertyType == typeof(DateTime?)
                                        select x.Name;
                propertyNames.AddRange(propertyNames2);
            }

            message += \"Entry \" + i++ + \" \" + type.Name + \": \" + string.Join(\"; \",propertyNames.Select(x =>
                string.Format(\"\'{0}\' = \'{1}\'\",x,entry1.CurrentValues[x])));
        }
        return new Exception(message,dbUpdateException);
    }
}
    ,        当我的实体VAlidation Erros遇到问题时,此代码有助于发现我的问题。它告诉我实体定义的确切问题。 在需要覆盖storeDB.SaveChanges()的地方尝试以下代码。在下面尝试捕获块。
  try
{
         if (TryUpdateModel(theEvent))
         {
             storeDB.SaveChanges();
             return RedirectToAction(\"Index\");
         }
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
    Exception raise = dbEx;
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            string message = string.Format(\"{0}:{1}\",validationErrors.Entry.Entity.ToString(),validationError.ErrorMessage);
            // raise a new exception nesting
            // the current instance as InnerException
            raise = new InvalidOperationException(message,raise);
        }
    }
    throw raise;
}
    ,        我今天遇到了这个错误,暂时无法解决,但是我意识到这是在向模型中添加了25英镑之后,并且一些开发种子数据并未填充所有必填字段。 因此,请注意,如果通过某种初始化策略(例如
DropCreateDatabaseIfModelChanges
)更新数据库时遇到此错误,则必须确保种子数据满足并满足任何模型数据验证属性。 我知道这与问题中的问题稍有不同,但这是一个很普遍的问题,所以我认为对于与我自己有相同问题的其他人,我会在答案中添加更多内容。 希望这对其他人有帮助:)     ,        我认为为每个
SaveChanges()
操作添加try / catch不是一个好习惯,最好将其集中化: 将此类添加到主
DbContext
类中:
public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        string errorMessages = string.Join(\"; \",ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage));
        throw new DbEntityValidationException(errorMessages);
    }
}
这将覆盖上下文的
SaveChanges()
方法,并且您将获得一个逗号分隔的列表,其中包含所有实体验证错误。 这也可以改进,以在生产环境中记录错误,而不仅仅是抛出错误。 希望这会有所帮助。     ,        这是Tony的扩展名... :-) 对于Entity Framework 4.x,如果要获取键字段的名称和值,以便知道哪个实体实例(数据库记录)有问题,则可以添加以下内容。这样可以从您的DbContext对象访问功能更强大的ObjectContext类成员。
// Get the key field name & value.
// This assumes your DbContext object is \"_context\",and that it is a single part key.
var e = ((IObjectContextAdapter)_context).ObjectContext.ObjectStateManager.GetObjectStateEntry(validationErrors.Entry.Entity);
string key = e.EntityKey.EntityKeyValues[0].Key;
string val = e.EntityKey.EntityKeyValues[0].Value;
    ,        我不喜欢例外 我注册了OnSaveChanges并拥有了
var validationErrors = model.GetValidationErrors();

var h = validationErrors.SelectMany(x => x.ValidationErrors
                                          .Select(f => \"Entity: \" 
                                                      +(x.Entry.Entity) 
                                                      + \" : \" + f.PropertyName 
                                                      + \"->\" + f.ErrorMessage));
    ,当您尝试保存具有验证错误的实体时,也会发生此错误。造成这种情况的一种好方法是在保存到数据库之前忘记检查ModelState.IsValid。     ,        确保如果数据库行中有nvarchar(50),则不要在其中插入50个以上的字符。愚蠢的错误,但花了我3个小时才弄清楚。     ,        这可能是由于特定列允许的最大字符数所致,例如在sql中,一个字段可能具有以下数据类型“ 33”,但从用户输入的字符数大于指定的字符数,因此会出现错误。     ,        我几天前在更新数据库时也遇到了同样的问题。就我而言,几乎没有添加新的不可为空的列进行维护,而导致异常的代码未提供这些列。我弄清楚了这些字段,并为其提供了值,并对其进行了解析。     ,        谢谢您的回答,这对我有很大帮助。 正如我在Vb.Net中编写的代码一样,此Vb.Net的Bolt代码
Try
   Return MyBase.SaveChanges()
Catch dbEx As Validation.DbEntityValidationException
   For Each [error] In From validationErrors In dbEx.EntityValidationErrors
                       From validationError In validationErrors.ValidationErrors
                       Select New With { .PropertyName = validationError.PropertyName,.ErrorMessage = validationError.ErrorMessage,.ClassFullName = validationErrors.Entry.Entity
                                                                    .GetType().FullName}

        Diagnostics.Trace.TraceInformation(\"Class: {0},[error].ClassFullName,[error].PropertyName,[error].ErrorMessage)
   Next
   Throw
End Try
    ,        它可能是由未由模型填充的Property引起的。而是由Controller填充的,这可能导致此错误。解决此问题的方法是在应用ModelState验证之前分配属性。 第二个假设是。您可能已经在数据库中有数据    并尝试对其进行更新,但现在正在获取它。     ,        在我的情况下,我有一个表列名Path,我设置的数据类型是varchar(200)。将其更新为nvarchar(max)之后,我已经从edmx中删除了该表,然后再次添加了该表,它对我来说是正确的。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-