我首先在Entity Framework 4.1
代码中有一个简单的代码:
PasmISOContext db = new PasmISOContext();
var user = new User();
user.CreationDate = DateTime.Now;
user.LastActivityDate = DateTime.Now;
user.LastLoginDate = DateTime.Now;
db.Users.Add(user);
db.SaveChanges();
user.Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") };
db.SaveChanges();
db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") } });
db.SaveChanges();
问题是我收到错误
保存不公开外键的实体时发生错误 他们关系的属性。 EntityEntries属性将 返回null,因为无法将单个实体标识为源 例外。可以在保存时处理异常 通过在实体类型中公开外键属性更容易。看到 InnerException以获取详细信息。
at
db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") } });
db.SaveChanges();
我不明白为什么类似的操作有效。我的模型或ef-code-first有问题吗?
public class Avatar
{
[Key]
public int Id { get; set; }
[Required]
public string LinkInString { get; set; }
[NotMapped]
public Uri Link
{
get { return new Uri(LinkInString); }
set { LinkInString = value.AbsoluteUri; }
}
}
public class User
{
[Key]
public int Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public Avatar Avatar { get; set; }
public virtual ICollection<Question> Questions { get; set; }
public virtual ICollection<Achievement> Achievements { get; set; }
public DateTime CreationDate { get; set; }
public DateTime LastLoginDate { get; set; }
public DateTime LastActivityDate { get; set; }
}
答案 0 :(得分:155)
对于那些仍然会在正确定义所有键的情况下出现此错误的人,请查看您的实体,并确保不要将datetime字段留空值。
答案 1 :(得分:11)
出于任何原因,可能会抛出此错误消息。 'InnerException'属性(或其InnerException,或者它的InnerException等)包含问题的实际主要原因。
了解问题发生的地方当然是有用的 - 工作单元中的哪个对象导致问题?异常消息通常会在“EntityEntries”属性中告诉您,但在这种情况下,由于某种原因,无法完成。这种诊断复杂性 - “EntityEntries”属性为空 - 显然是因为某些实体不会为其关系公开外键属性。'
即使OP由于未能为DateTime
的第二个实例初始化User
而得到错误,它们也会得到诊断并发症 - 'EntityEntries'为空,并且顶层令人困惑消息...因为他们的某个实体没有'公开外键属性'。要解决此问题,Avatar
应定义public virtual ICollection<User> Users { get; set; }
属性。
答案 2 :(得分:6)
通过添加FK属性解决了该问题。
答案 3 :(得分:3)
在我的情况下,以下情况给了我相同的例外:
想象一下代码第一个EF模型,其中有一个Garage
实体,其中包含Car
个实体的集合。我需要从车库中取出一辆车,所以我最终得到的代码如下:
garageEntity.Cars.Remove(carEntity);
相反,它应该看起来像这样:
context.Cars.Remove(carEntity);
答案 4 :(得分:2)
仅适用于可能遇到类似问题的其他人。我有同样的错误,但出于不同的原因。在其中一个子对象中,我将[Key]定义为对于不同的保存是相同的值。我这是一个愚蠢的错误,但错误信息并不会立即引发您的问题。
答案 5 :(得分:2)
在我的情况下,由于EF错误地创建了迁移,因此抛出了异常。 它错过了在第二个表上设置 identity:true 。因此,请进入创建相关表的迁移,并检查是否错过了添加标识。
CreateTable(
"dbo.LogEmailAddressStats",
c => new
{
Id = c.Int(nullable: false, identity: true),
EmailAddress = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.LogEmailAddressStatsFails",
c => new
{
Id = c.Int(nullable: false), // EF missed to set identity: true!!
Timestamp = c.DateTime(nullable: false),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.LogEmailAddressStats", t => t.Id)
.Index(t => t.Id);
Id列应具有标识(即自动递增!),因此这必须是EF错误。
您可以使用SQL手动将标识直接添加到数据库,但我更喜欢使用实体框架。
如果您遇到同样的问题,我会看到两个简单的解决方案:
替代1
使用
反转错误创建的迁移update-database -target:{insert the name of the previous migration}
然后手动将 identity:true 添加到迁移代码中,然后再次 update-database 。
Alt 2
您创建了一个添加标识的新迁移。如果您没有对模型进行任何更改,则运行
add-migration identity_fix
它将创建一个空迁移。然后只需添加此
public partial class identity_fix : DbMigration
{
public override void Up()
{
AlterColumn("dbo.LogEmailAddressStatsFails", "Id", c => c.Int(nullable: false, identity: true));
}
public override void Down()
{
AlterColumn("dbo.LogEmailAddressStatsFails", "Id", c => c.Int(nullable: false));
}
}
答案 6 :(得分:0)
另一个答案:
我用过这个:
public List<EdiSegment> EdiSegments { get; set; }
而不是:
public virtual ICollection<EdiSegment> EdiSegments { get; set; }
并收到上面提到的错误消息。
答案 7 :(得分:0)
我有同样的错误,在我的情况下,问题是我添加了一个已经加载的关系对象&#34; AsNoTracking&#34;。我不得不重新加载关系属性。
BTW,有人建议使用&#34;附加&#34;对于已经存在于db中的关系,我还没有尝试过这个选项。答案 8 :(得分:0)
我有同样的问题。在我的情况下,它是由于datetime字段的空值。我不得不将值传递到日期时间,一切都很顺利
答案 9 :(得分:0)
在我的情况下,问题是我不正确地重命名了一个列,因此迁移产生了两列,一个名为“TeamId”,一个名为“TeamID”。 C#关心,SQL没有。
答案 10 :(得分:0)
这里又是另一种情况。 查询被转换为列表,在执行此操作时,它通过构造函数创建实体,以便在ToList()之后的linq表达式中进行比较。这创建了在linq表达式完成后进入删除状态的实体 然而!有一个小的调整在构造函数中创建了另一个实体,因此这个新实体被链接到标记为已删除的实体。
一些代码来说明:
query.Except(_context.MyEntitySetSet()
.Include(b => b.SomeEntity)
.Where(p => Condition)
.ToList() // This right here calls the constructor for the remaining entities after the where
.Where(p => p.Collection.First(b => Condition).Value == 0)
.ToList();
MyEntity的构造函数:
public partial class MyEntity
{
protected MyEntity()
{
// This makes the entities connected though, this instance of MyEntity will be deleted afterwards, the instance of MyEntityResult will not.
MyEntityResult = new MyEntityResult(this);
}
}
我的解决方案是确保整个表达式都在IQueryable中完成,这样就不会创建任何对象。
答案 11 :(得分:0)
我不完全确定它会对您的情况有所帮助,因为我正在使用Fluent API设置我的表,但是,据我所知,无论是否使用数据注释设置架构,问题就出现了(属性)或Fluent API(配置)。
EF(v.6.1.3)中似乎存在一个错误,因为它在将数据库更新到下一次迁移时忽略了对模式的某些更改。围绕它的最快路线是(在开发阶段)从数据库中删除所有表并再次从init阶段进行迁移。
如果您已经投入生产,我发现最快的解决方案是手动更改数据库中的架构,或者,如果您希望对更改进行版本控制,请手动操作方法 Up()您的迁移中和 Down()。
答案 12 :(得分:0)
今天我遇到了这个问题并尝试了上面发布的可能的解决方案,但没有一个帮助我。我实现了UnitOfWork
模式,系统在添加所有记录后最后提交了数据。
在我的情况下,系统正在组合两个模型并查询数据库
无效的对象名称'dbo.RoleModelUserModel'。
其中这些是两个不同的模型。
我通过重新排序插入语句并首先添加父实体来修复此问题。在这种情况下,首先添加用户并解决问题。
答案 13 :(得分:0)
经过一番调查,我发现虽然.Net在 SQL Server Compact中支持01/01/0001 00:00:00
的最小日期(DateTime.MinValue)和31/12/9999 23:59:59
的最大日期(DateTime.MaxValue)版本的最小日期为01/01/1753 00:00:00
。
当我输入的日期大于01/01/1753 00:00:00
时,此错误消失了。