如何在自动生成id时使用entiity Framework核心插入数据?

时间:2017-08-09 13:32:27

标签: mysql entity-framework linq entity-framework-core asp.net-core-webapi

我需要在数据库的2个表中插入一行。这两个表之间的关系是一对多。这是他们的模型

NSUInteger width, height, i;
CGContextRef context;
void *data;
CGColorSpaceRef colorSpace;
UIFont *font;

font = [UIFont fontWithName:name size:size];

width = (NSUInteger)dimensions.width;
if ((width != 1) && (width & (width - 1))) {
    i = 1;
    while (i < width)
        i *= 2;
    width = i;
}
height = (NSUInteger)dimensions.height;
if ((height != 1) && (height & (height - 1))) {
    i = 1;
    while (i < height)
        i *= 2;
    height = i;
}

colorSpace = CGColorSpaceCreateDeviceGray();
data = calloc(height, width);
context = CGBitmapContextCreate(data, width, height, 8, width, colorSpace, kCGImageAlphaNone);

CGColorSpaceRelease(colorSpace);

CGContextSetGrayFillColor(context, 1.0, 1.0);
CGContextTranslateCTM(context, 0.0, height);
CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential
UIGraphicsPushContext(context);

NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];

NSDictionary *attrsDictionary = @{
                                  NSFontAttributeName: font,
                                  NSBaselineOffsetAttributeName: @1.0F,
                                  NSParagraphStyleAttributeName: style
                                  };

[string drawInRect:CGRectMake(0, 0, dimensions.width, dimensions.height)
    withAttributes:attrsDictionary];

UIGraphicsPopContext();

// Here I use "void *data" to obtain an OpenGL texture
// ...
// ...

CGContextRelease(context);
free(data);

这是上下文

public partial class Task
{
    public Task()
    {
        TaskOwner = new HashSet<TaskOwner>();
    }

    public int Id { get; set; }
    public string Action { get; set; }
    public int ActualEffort { get; set; }
    public DateTime AssignationDate { get; set; }
    public int EstEffort { get; set; }
    public DateTime EstEnd { get; set; }
    public bool IsComplete { get; set; }
    public int ProjectId { get; set; }
    public string Status { get; set; }

    public virtual ICollection<TaskOwner> TaskOwner { get; set; }
    public virtual Project Project { get; set; }
}

public partial class TaskOwner
{
    public int Id { get; set; }
    public int EmployeId { get; set; }
    public int TaskId { get; set; }

    public virtual Employe Employe { get; set; }
    public virtual Task Task { get; set; }
}

一个任务可以由多个TaskOwner拥有。我试过这个approch:

modelBuilder.Entity<Task>(entity =>
        {
            entity.HasIndex(e => e.ProjectId)
                .HasName("FKTask25514");

            entity.Property(e => e.Id)
                .HasColumnName("id")
                .HasColumnType("int(10)");

            entity.Property(e => e.Action)
                .IsRequired()
                .HasColumnName("action")
                .HasColumnType("varchar(255)");

            entity.Property(e => e.ActualEffort)
                .HasColumnName("actual_effort")
                .HasColumnType("int(10)");

            entity.Property(e => e.AssignationDate).HasColumnName("assignation_date");

            entity.Property(e => e.EstEffort)
                .HasColumnName("est_effort")
                .HasColumnType("int(10)");

            entity.Property(e => e.EstEnd).HasColumnName("est_end");

            entity.Property(e => e.IsComplete).HasColumnType("tinyint(1)");

            entity.Property(e => e.ProjectId)
                .HasColumnName("project_id")
                .HasColumnType("int(10)");

            entity.Property(e => e.Status)
                .IsRequired()
                .HasColumnName("status")
                .HasColumnType("varchar(255)");

            entity.HasOne(d => d.Project)
                .WithMany(p => p.Task)
                .HasForeignKey(d => d.ProjectId)
                .OnDelete(DeleteBehavior.Restrict)
                .HasConstraintName("FKTask25514");
        });

        modelBuilder.Entity<TaskOwner>(entity =>
        {
            entity.ToTable("Task_Owner");

            entity.HasIndex(e => e.EmployeId)
                .HasName("FKTask_Owner320287");

            entity.HasIndex(e => e.TaskId)
                .HasName("FKTask_Owner395416");

            entity.Property(e => e.Id)
                .HasColumnName("id")
                .HasColumnType("int(10)");

            entity.Property(e => e.EmployeId)
                .HasColumnName("employe_id")
                .HasColumnType("int(10)");

            entity.Property(e => e.TaskId)
                .HasColumnName("task_id")
                .HasColumnType("int(10)");

            entity.HasOne(d => d.Employe)
                .WithMany(p => p.TaskOwner)
                .HasForeignKey(d => d.EmployeId)
                .OnDelete(DeleteBehavior.Restrict)
                .HasConstraintName("FKTask_Owner320287");

            entity.HasOne(d => d.Task)
                .WithMany(p => p.TaskOwner)
                .HasForeignKey(d => d.TaskId)
                .OnDelete(DeleteBehavior.Restrict)
                .HasConstraintName("FKTask_Owner395416");
        });

然后将其保存到数据库中,但我总是解除此错误:

  

使用“Models.TaskOwner”类型检测到自引用循环。 Path'[6] .taskOwner [0] .employe.taskOwner'。

如果可以的话,我会使用我刚创建的任务的id并将其链接到taskOwner模型,但由于id是自动生成的,我不能或者至少我不知道如何。我究竟做错了什么?做我想要完成的事情的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

因此Task有零个或多个TaskOwners。每个TaskOwner只有一个Task。没有TaskOwners没有Task

这意味着,如果数据库中存在TaskOwner,则不能拥有第二个Task。但是,你可以让它拥有一个不同的Task而不是它现在拥有的{。}}。

如果向数据库中引入(添加)与数据库中现有对象关系的对象,则可以使用相关对象的Id或对象本身(当然,它具有非零值) ID)。

如果相关对象也是新对象,只需将相关对象分配给要添加的对象即可。您不必单独添加相关对象。

请注意,只要您没有使用SaveChanges,就不能使用任何新对象的ID。

介绍一个拥有现有任务和现有员工的TaskOwner

using (var dbContext = new MyDbContext())
{
    int employeeId = FetchEmployeeId(...);
    int taskId = FetchTaskId(...);

    TaskOwner introducedTaskOwner = dbContext.TaskOwners.Add(new TaskOwner()
    {
        // don't fill the ID!
        EmployeeId = employeeId,
        TaskId = taskId,

        ... // other properties
    });
    dbContext.SaveChanges();

    // now the introduced task owner has an Id!
    return introducedTaskOwner;
}

将TaskOwner与新任务一起引入。使用现有员工

现在你无法填写TaskId,而是填写任务:

using (var dbContext = new MyDbContext())
{
    int employeeId = FetchEmployeeId(...);

    TaskOwner introducedTaskOwner = dbContext.TaskOwners.Add(new TaskOwner()
    {
        // don't fill the TaskOwner ID!
        EmployeeId = employeeId,

        // Give the Task owner a non-existing Task:
        Task = new Task()
        {
            // don't fill the Task ID!
            // don't fill the collection of TaskOwners

            ... // fill other Task properties
        }

        ... // other task owner properties
    });
    dbContext.SaveChanges();

    // now both the task owner and the task are introduced. Both have an ID
    Debug.Assert(introducedTaskOwner.Id != 0);
    Debug.Assert(intrducedTaskOwner.TaskId != 0);
    Debug.Assert(introducedTaskOwner.Task.Id != 0);
}

如果你想要,你可以先介绍Task,然后再介绍TaskOwner。只要您没有使用SaveChanges,就不能使用任何Id。

using (var dbContext = new MyDbContext())
{
    int employeeId = FetchEmployeeId(...);

    Task introducedTask = dbContext.Tasks.Add(new Task()
    {
        // don't fill the Task ID!
        TaskOwners = new List<TaskOwner>(); // This Task has no owners yet

            ... // fill other Task properties
    });

    TaskOwner introducedTaskOwner = dbContext.TaskOwners.Add(new TaskOwner()
    {
        // don't fill the TaskOwner ID!
        EmployeeId = employeeId,

        // Give the Task owner a the introduced task
        Task = introducedTask,

        ... // other task owner properties
    });
    dbContext.SaveChanges();
}

您也可以反过来执行此操作:您可以将TaskOwner添加到现有(或新添加的)任务

using (var dbContext = new MyDbContext())
{
    int employeeId = FetchEmployeeId(...);

    // get existing task:
    Task existingTask = dbContext.Tasks
        .Where(task => task.ActualEffort > ...)
        .OrderBy(task => task.ActualEffort)
        .FirstOrDefault();

    // add an owner to the task owners collection:
    existingTask.TaskOwners.Add(new TaskOwner()
    {
        // don't fill the TaskOwner ID!
        EmployeeId = employeeId,
        // no need to fill the TaskId, nor the Task
        // Entity Framework knows the Task to which it belongs, because you 
        // add it to the TaskOwners collection
        ...           
    });
    dbContext.SaveChanges();
}

结论:只要您没有Id,请使用完整对象。如果尚未添加对象,实体框架将添加它

答案 1 :(得分:0)

首先,您需要保存Models.Task并访问自动生成的ID,然后保存TaskOwner模型。