Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.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# 实体框架核心保存单个实体而不是更新_C#_Sql_Entity Framework - Fatal编程技术网

C# 实体框架核心保存单个实体而不是更新

C# 实体框架核心保存单个实体而不是更新,c#,sql,entity-framework,C#,Sql,Entity Framework,所以我一直在阅读,关于这方面的大多数问题是,你必须分离上下文,解决方案通常是创建一些外键。然而,我的问题是在一个实体上,而不是与这个实体的关系,我有外键,我可以根据需要来考虑。我认为这与使用GUID作为主键有关 我的犯罪实体是: public class Customer { public Guid Id { get; set; } public string Name { get; set; } public DateTime CreatedAt { get; set;

所以我一直在阅读,关于这方面的大多数问题是,你必须分离上下文,解决方案通常是创建一些外键。然而,我的问题是在一个实体上,而不是与这个实体的关系,我有外键,我可以根据需要来考虑。我认为这与使用GUID作为主键有关

我的犯罪实体是:

public class Customer
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public DateTime CreatedAt { get; set; }
    public virtual ICollection<Organization> Organizations { get; set; }
}
我用以下代码保存它:

public class AddCustomer : ICommand
{
    public Guid CustomerId { get; set; }
    public string Name { get; set; }
}

[Transactional]
internal sealed class HandleAddCustomer : IHandleCommand<AddCustomer>
{
    private readonly IEntityWriter<Customer> _writer;
    public HandleAddCustomer(IEntityWriter<Customer> writer)
    {
        _writer = writer;
    }

    public Task HandleAsync(AddCustomer command)
    {
        var customer = new Customer
        {
            Id = command.CustomerId,
            Name = command.Name,
            CreatedAt = DateTime.Now
        };

        _writer.Save(customer);

        return Task.CompletedTask;
    }
}
这一切都很好,很漂亮,直到我发送相同的ID

{
    "CustomerId": "692da47a-3886-42bb-a1ac-d853d315109a",
    "Name": "New name"
}
然后我得到一个外键冲突,因为它试图将其作为新行插入,这当然会导致一个重复的主键。所以我认为,我的罪魁祸首是处理身份证。我见过有人建议

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
但是我的主键不是由数据库生成的(来自一个现有的不相交系统),所以我只希望它与主键保持一致,并确保它是同一个实体,并且必须更新它。我需要先用一些数据查询数据库吗

if(_querys().Where(c=>c.Id==command.Id).FirstOrDefault()!=null){…//客户已经存在,更新实体中的名称并再次保存它

每次执行命令时手动检查现有实体感觉有点像意大利面条,但尽管我对EF的经验有限(尤其是EF Core),但我可能对它的期望有点过高

Edit:我一直在挖掘一位过去的员工编写的一些代码,似乎EF集成(尤其是保存)只设置实体的实际状态:

 public void Save(TEntity entity)
        {
            var context = _contextProvider();
            var entry = context.Entry(entity);

            // If it is not tracked by the context, add it to the context
            if (entry.State == EntityState.Detached)
            {
                // This also sets the entity state to added.
                context.Set<TEntity>().Add(entity);
            }
            else
            {
                // Tells the context that the entity should be updated during saving changes
                entry.State = EntityState.Modified;
            }
        }

但是关于Frederik的建议,我可能需要更新库以同时使用AddOrUpdate()偷偷编辑,这似乎还没有在EF Core.Yay中实现。

是的,如果ID已经存在或不存在,您需要首先查询DB。

有一个名为AddOrUpdate()的方法

您可以使用。这是一种扩展方法,您可以在此处了解更多信息:

您可能必须更改以下内容的实现:\u writer.Save(customer); 它应该是这样的:

public void Save(Customer customer)
{
   var dalCustomer = context.Customers.FirstOrDefault(c => c.Id = entity.Id);
   if (dalCustomer == null)
   {
      dalCustomer = new Customer();
      context.Customers.Add(dalCustomer);
   }

   dalCustomer.Name = customer.Name;
   dalCustomer.CreatedAt = DateTime.Now;

   context.SaveChanges();
}

(此代码未经测试或编译)

而不是_writer.Save(customer)在您的客户更改后,您是否尝试过使用db.SaveChanges();不幸的是,这尚未在EF Core中实现,但我认为现在的方法是创建自己的版本。
{
    "CustomerId": "692da47a-3886-42bb-a1ac-d853d315109a",
    "Name": "New name"
}
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
 public void Save(TEntity entity)
        {
            var context = _contextProvider();
            var entry = context.Entry(entity);

            // If it is not tracked by the context, add it to the context
            if (entry.State == EntityState.Detached)
            {
                // This also sets the entity state to added.
                context.Set<TEntity>().Add(entity);
            }
            else
            {
                // Tells the context that the entity should be updated during saving changes
                entry.State = EntityState.Modified;
            }
        }
public async Task ExecuteAsync()
        {
            await _contextProvider().SaveChangesAsync().ConfigureAwait(false);
        }
db.Customer.AddOrUpdate(customer); 
public void Save(Customer customer)
{
   var dalCustomer = context.Customers.FirstOrDefault(c => c.Id = entity.Id);
   if (dalCustomer == null)
   {
      dalCustomer = new Customer();
      context.Customers.Add(dalCustomer);
   }

   dalCustomer.Name = customer.Name;
   dalCustomer.CreatedAt = DateTime.Now;

   context.SaveChanges();
}