Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# HasRequired和WithOptional不生成一对一关系_C#_Entity Framework_Visual Studio 2017_Entity Framework 6_Fluent - Fatal编程技术网

C# HasRequired和WithOptional不生成一对一关系

C# HasRequired和WithOptional不生成一对一关系,c#,entity-framework,visual-studio-2017,entity-framework-6,fluent,C#,Entity Framework,Visual Studio 2017,Entity Framework 6,Fluent,我有两个非常简单的对象: public class GenericObject { public int Id { get; set; } public string description { get; set; } public User UserWhoGeneratedThisObject { get; set; } } public class User { public int Id { get; set; } public string

我有两个非常简单的对象:

public class GenericObject
{
    public int Id { get; set; }
    public string description { get; set; }
    public User UserWhoGeneratedThisObject { get; set; }
}

public class User
{
    public int Id { get; set; }  
    public string Name { get; set; }
    public string Lastname { get; set; }
}
我正在重写OnModelCreating函数以声明对象的关系:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<GenericObject>().HasRequired(u => u.UserWhoGeneratedThisObject)
                                   .WithOptional();
    }
当我将myObject添加到数据库时,我是否应该遇到异常,因为我没有为它分配用户对象?(注释掉的行)我希望在这种情况下看到异常,但代码工作正常。更糟糕的是,如果我在ctx.SaveChanges()之后添加以下两行:


我发现变量u(GenericObject)实际上指向我在数据库中创建的用户,尽管我没有将用户分配给GenericObject。

您需要设置两个导航属性:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   modelBuilder.Entity<GenericObject>()
      .HasRequired(genericObject => genericObject.UserWhoGeneratedThisObject)
      .WithOptional(user => user.GenericObject);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasRequired(genericObject=>genericObject.UserWhoGeneratedThis对象)
.WithOptional(用户=>user.generiObject);
}
您应该阅读:

守则:

using (var ctx = new Tests6Context()) {
    GenericObject myObject = new GenericObject();
    myObject.description = "testobjectdescription";
    User usr = new User() { Name = "Test" };
    ctx.Users.Add(usr);
    //myObject.UserWhoGeneratedThisObject = usr;
    ctx.GenericObjects.Add(myObject);


    myObject = new GenericObject();
    myObject.description = "testobjectdescription 2";
    usr = new User() { Name = "Test 2" };
    ctx.Users.Add(usr);
    //myObject.UserWhoGeneratedThisObject = usr;
    ctx.GenericObjects.Add(myObject);

    ctx.SaveChanges();
}
抛出:

System.Data.Entity.Infrastructure.DbUpdateException:无法确定“ef6tests.GenericObject_UserWhoGeneratedThisObject”关系的主端。多个添加的实体可能具有相同的主键

在简单情况下,一个新用户和一个新GenericObject EF推断出处于相同状态的两个实体之间可能存在的唯一关系。在其他情况下,他抛出

当我将myObject添加到数据库时,我是否应该遇到异常,因为我没有为它分配用户对象?(注释掉的行)

我认为不会,因为“OnModelCreating”函数实现没有在数据库中创建一对一关系。 应创建将由“[ForeignKey]”属性标记为外键的GenericObject属性,以在“User”类中创建一对一关系。“GenericObject”属性应添加到“User”类中,并用虚拟修饰符标记。现在,“OnModelCreating”的实现将配置这些类之间的关系。 以下是模型示例:

public class User
    {
        [Key]
        public int Id { get; set; }

        public string Name { get; set; }

        public string Lastname { get; set; }

        [ForeignKey("GenericObject")]
        public int GenericObjectId { get; set; }

        public virtual GenericObject GenericObject { get; set; }
    }

public class GenericObject
    {
        [Key]
        public int Id { get; set; }

        public string Description { get; set; }        

        public virtual User UserWhoGeneratedThisObject { get; set; }
    }

应首先创建泛型对象,并将创建的对象id添加到新用户以避免此异常(若将外键放入用户,则会出现这种情况)

希望我能清楚地回答你的问题。

TL;DR

这种行为并不特定于
一对一
关系,
一对多
的行为方式完全相同

如果要使EF对当前代码引发异常,请为
generiobject

modelBuilder
    .Entity<GenericObject>()
    .HasRequired(u => u.UserWhoGeneratedThisObject)
    .WithOptional()
    .Map(config =>
    {
        config.MapKey("UserId");
    });
配置

modelBuilder
    .Entity<GenericObject>()
    .HasRequired(u => u.UserWhoGeneratedThisObject)
    .WithOptional();
modelBuilder
    .Entity<GenericObject>()
    .HasRequired(o => o.UserWhoGeneratedThisObject)
    .WithMany()
    .HasForeignKey(o => o.UserId);
modelBuilder
    .Entity<GenericObject>()
    .HasRequired(u => u.UserWhoGeneratedThisObject)
    .WithOptional()
    .Map(config =>
    {
        config.MapKey("UserId");
    });
执行查询

INSERT [dbo].[GenericObjects]([Id], [Description])
VALUES (@0, @1)

-- @0: '0' (Type = Int32)

-- @1: 'some description' (Type = String, Size = -1)
例外情况

INSERT语句与外键约束“FK_dbo.GenericObjects_dbo.UserObjects_Id”冲突。冲突发生在数据库“TestProject”、表“dbo.UserObjects”、列“Id”中。 声明已终止

由于
generiobject
是EF执行
insert
查询的唯一实体,因此查询失败,因为数据库中没有
Id
等于
0
UserObject

测试2。创建1个UserObject和一个GenericObject

var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

context.GenericObjects.Add(myObject);
context.SaveChanges();
var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

UserObject user = new UserObject
{
    Name = "user"
};

context.UserObjects.Add(user);
context.GenericObjects.Add(myObject);
context.SaveChanges();
var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

UserObject user = new UserObject
{
    Name = "user"
};
UserObject user2 = new UserObject
{
    Name = "user"
};

context.UserObjects.Add(user);
context.UserObjects.Add(user2);
context.GenericObjects.Add(myObject);
context.SaveChanges();
执行的查询

INSERT [dbo].[UserObjects]([Name])
VALUES (@0)
SELECT [Id]
FROM [dbo].[UserObjects]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()

-- @0: 'user' (Type = String, Size = -1)

INSERT [dbo].[GenericObjects]([Id], [Description])
VALUES (@0, @1)

-- @0: '10' (Type = Int32)

-- @1: 'some description' (Type = String, Size = -1)
INSERT [dbo].[UserObjects]([Name])
VALUES (@0)
SELECT [Id]
FROM [dbo].[UserObjects]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()

-- @0: 'user' (Type = String, Size = -1)

-- Executing at 14.03.2019 18:52:35 +02:00

INSERT [dbo].[GenericObjects]([Description], [UserId])
VALUES (@0, @1)
SELECT [Id]
FROM [dbo].[GenericObjects]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()

-- @0: 'some description' (Type = String, Size = -1)

-- @1: '3' (Type = Int32)
现在上下文包含
UserObject
(Id=0)和
generiobject
(Id=0)。EF认为
generiobject
引用了
UserObject
,因为它的外键等于0,
UserObject
主键等于0。因此,首先EF插入<代码> USER对象< /代码>作为主体,因为它考虑了代码>通用对象/<代码>,依赖于该用户,它使用返回<代码>用户对象.ID/COD>并执行第二个插入,并且一切都很好。 测试3。创建2个UserObject和一个GenericObject

var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

context.GenericObjects.Add(myObject);
context.SaveChanges();
var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

UserObject user = new UserObject
{
    Name = "user"
};

context.UserObjects.Add(user);
context.GenericObjects.Add(myObject);
context.SaveChanges();
var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

UserObject user = new UserObject
{
    Name = "user"
};
UserObject user2 = new UserObject
{
    Name = "user"
};

context.UserObjects.Add(user);
context.UserObjects.Add(user2);
context.GenericObjects.Add(myObject);
context.SaveChanges();
例外情况

EntityFramework.dll中出现“System.Data.Entity.Infrastructure.DbUpdateException”

其他信息:无法确定“TestConsole.Data.GenericObject_UserWhoGeneratedThisObject”关系的主体端。多个添加的实体可能具有相同的主键

EF发现在
Id
等于
0
generiobject.Id
等于0的上下文中有2个
UserObject
,因此框架无法明确连接实体,因为存在多个可能的选项

一对多

public class GenericObject
{
    public int Id { get; set; }

    public string Description { get; set; }

    public int UserId { get; set; } //this property is essential to illistrate the problem

    public UserObject UserWhoGeneratedThisObject { get; set; }
}

public class UserObject
{
    public int Id { get; set; }

    public string Name { get; set; }
}
配置

modelBuilder
    .Entity<GenericObject>()
    .HasRequired(u => u.UserWhoGeneratedThisObject)
    .WithOptional();
modelBuilder
    .Entity<GenericObject>()
    .HasRequired(o => o.UserWhoGeneratedThisObject)
    .WithMany()
    .HasForeignKey(o => o.UserId);
modelBuilder
    .Entity<GenericObject>()
    .HasRequired(u => u.UserWhoGeneratedThisObject)
    .WithOptional()
    .Map(config =>
    {
        config.MapKey("UserId");
    });
执行的查询非常类似于
one-to-one
test2。唯一的区别是现在
GenericObject
有单独的
UserId
外键。推理也是如此。上下文包含
UserObject
实体和
Id
相等的
0
generiobject
UserId
相等的
UserObject
,因此EF认为它们已连接并执行
UserObject
的插入,然后获取
UserObject.Id
并执行第二次插入

测试3。创建2个UserObject和一个GenericObject

var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

context.GenericObjects.Add(myObject);
context.SaveChanges();
var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

UserObject user = new UserObject
{
    Name = "user"
};

context.UserObjects.Add(user);
context.GenericObjects.Add(myObject);
context.SaveChanges();
var context = new AppContext();

GenericObject myObject = new GenericObject
{
    Description = "some description"
};

UserObject user = new UserObject
{
    Name = "user"
};
UserObject user2 = new UserObject
{
    Name = "user"
};

context.UserObjects.Add(user);
context.UserObjects.Add(user2);
context.GenericObjects.Add(myObject);
context.SaveChanges();
一对一
中的代码相同。它执行相同的查询并产生相同的异常。原因是一样的

从这些测试中可以看出,问题并非特定于一对一关系

但是,如果我们不将
UserId
添加到
GenericObject
,该怎么办?在这种情况下,EF将为我们生成
userwhogeneratedthis object_Id
外键,现在数据库中有外键,但没有映射到它的属性。在这种情况下,每个测试都会立即抛出以下异常

using (var ctx = new TestContext())
{
    GenericObject myObject = new GenericObject();
    myObject.description = "testobjectdescription";
    User usr = new User() { Name = "Test"};
    ctx.Users.Add(usr);
    //myObject.UserWhoGeneratedThisObject = usr;
    ctx.GenericObjects.Add(myObject);
    ctx.SaveChanges();
}
“AppContext.GenericObjects”中的实体参与“GenericObject_UserWhoGeneratedThisObject”关系。找到0个相关的“GenericObject\u Userwho生成此对象\u目标”。应为1“GenericObject\u Userwho生成此对象\u目标的用户”

为什么会发生这种情况?现在EF无法确定是否连接了
generiobject
UserObject