c# - 定义实体关系时如何为依赖操作指定有效顺序?

标签 c# entity-framework

我正在尝试对 Advertisement 进行更新插入包含 List<AdImage> 的对象. Advertisement包含对应于 User 的外键. user可以有零个或多个 Advertisements , 和一个 Advertisement有一个或多个 AdImages .

更新插入失败并显示以下内容:

An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types. See the InnerException for details.

内部异常在哪里:

Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

advertisement非常简单地实例化为:

var ad = new Advertisement
{
    AdImages = new List<AdImage>
    {
        new AdImage {Image = model.Image}
    },

    Message = model.Message,
    Title = model.Title,
    User = user,
};  

_aAdAppService.UpsertAdvertisement(ad);

有问题的实体定义为:

public class User : AbpUser<Tenant, User> 
{ // AbpUser is a 3rd party class which defines Id as a primary key

    public string AccessToken { get; set; }
    public long UserId { get; set; }

    public virtual List<Advertisement> Advertisements { get; set; }
}

public class Advertisement : Entity
{
    [Key]
    public long Id { get; set; }

    public string Title { get; set; }
    public string Message { get; set; }
    public List<AdImage> AdImages { get; set; }

    public virtual User User { get; set; }
}

public class AdImage : Entity
{
    [Key]
    public int Id { get; set; }
    public string Image { get; set; }

    public virtual Advertisement Advertisement { get; set; }
}

关系是这样定义的:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasMany(u => u.Advertisements)
        .WithRequired(x => x.User);

    modelBuilder.Entity<Advertisement>()
        .HasMany(a => a.AdImages)
        .WithRequired(x => x.Advertisement);

    modelBuilder.Entity<AdImage>()
        .HasRequired(x => x.Advertisement);

    base.OnModelCreating(modelBuilder);

}

错误信息是什么意思?我看不出我的关系是如何被错误定义的。我该如何解决这个问题?

最佳答案

这只是一条评论,但我不能在评论中写...

第一次看到异常

Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.

所以我尝试复制它。

这是我实现错过的类(class)和上下文的方式

public class Entity
{}

public class Tenant
{}

public class AbpUser<T1, T2>
{}



public Context(DbConnection connection)
    : base(connection, false)
{
}

public DbSet<Advertisement> Advertisements { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<AdImage> AdImages { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasMany(u => u.Advertisements)
        .WithRequired(x => x.User);

    modelBuilder.Entity<Advertisement>()
        .HasMany(a => a.AdImages)
        .WithRequired(x => x.Advertisement);

    modelBuilder.Entity<AdImage>()
        .HasRequired(x => x.Advertisement);

    base.OnModelCreating(modelBuilder);

}

这是EF在自动迁移时生成的DDL语句

ExecuteNonQuery==========
CREATE TABLE [AdImages] (
 [Id] int not null identity(1,1)
, [Image] text null
, [Advertisement_Id] int not null
);
ALTER TABLE [AdImages] ADD CONSTRAINT [PK_AdImages_87d4bad2] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [Advertisements] (
 [Id] int not null identity(1,1)
, [Title] text null
, [Message] text null
, [User_UserId] int not null
);
ALTER TABLE [Advertisements] ADD CONSTRAINT [PK_Advertisements_5d578c9a] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [Users] (
 [UserId] int not null identity(1,1)
, [AccessToken] text null
);
ALTER TABLE [Users] ADD CONSTRAINT [PK_Users_5d578c9a] PRIMARY KEY ([UserId])
ExecuteNonQuery==========
CREATE INDEX [IX_Advertisement_Id] ON [AdImages] ([Advertisement_Id])
ExecuteNonQuery==========
CREATE INDEX [IX_User_UserId] ON [Advertisements] ([User_UserId])
ExecuteNonQuery==========
ALTER TABLE [AdImages] ADD CONSTRAINT [FK_AdImages_Advertisements_Advertisement_Id] FOREIGN KEY ([Advertisement_Id]) REFERENCES [Advertisements] ([Id])
ExecuteNonQuery==========
ALTER TABLE [Advertisements] ADD CONSTRAINT [FK_Advertisements_Users_User_UserId] FOREIGN KEY ([User_UserId]) REFERENCES [Users] ([UserId])

所以,其实一切都如我们所料。

这里是我试过的测试

public static void Run(DbConnection connection)
{
    var ad = new Advertisement
    {
        AdImages = new List<AdImage>
        {
            new AdImage {Image = "MyImage"}
        },

        Message = "MyMessage",
        Title = "MyTitle",
        User = new User()
    };

    using (Context context = new Context(connection))
    {
        context.Advertisements.Add(ad);
        context.SaveChanges();
    }
}

在数据库上产生了这个查询

ExecuteDbDataReader==========
insert into [Users]([AccessToken])
values (null);
select [UserId]
from [Users]
where [UserId] = @@identity
ExecuteDbDataReader==========
insert into [Advertisements]([Title], [Message], [User_UserId])
values (@p0, @p1, @p2);
select [Id]
from [Advertisements]
where [Id] = @@identity
@p0 = MyTitle
@p1 = MyMessage
@p2 = 1
ExecuteDbDataReader==========
insert into [AdImages]([Image], [Advertisement_Id])
values (@p0, @p1);
select [Id]
from [AdImages]
where [Id] = @@identity
@p0 = MyImage
@p1 = 1

你的模型简直完美:)

所以问题出在其他地方。 它可能在代码中,周围,即
- modeluser 来自哪里?您在 Upsert 中使用的上下文相同还是不同?
- 你在 Upsert 中做什么?您是否更改了一些引用(从 model 到新对象)?
- 其他缺失的类(我留空的那些)可以吗?

关于c# - 定义实体关系时如何为依赖操作指定有效顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36188603/

相关文章:

c# - 在事件处理 C# 中创建事件变量需要什么?

c# - NotSupportedException 在 LINQ 和 EntityFramework 中使用 ToList()

.net - 导航属性 'SenderId' 不是类型 'Conversation' 上的声明属性

entity-framework - MVVM - 业务层在哪里映射?

entity-framework - 将属性映射到 Entity Framework CTP5 中的(不同命名的)外键字段

c# - 痛苦的泛型,运算符 '>=' 不能应用于类型 'T' 和 'T' 的操作数

c# - Response.End () 不会中止当前线程

c# - 使用 Silverlight 在运行时在 tabcontrol 中添加 TabItem

c# - 当 ID 字段 (PK) 自动递增时(带有 EF 的 MySQL),使用与之前相同的 Id 恢复已删除的记录

c# - Automapper.Mapper.CreateMap无法解析