繁体   English   中英

如何使用 EntityFramework Core 中的关系数据更新对象

[英]How update object with relation data in EntityFramework Core

我使用了Entity Framework Core并更新了一些与另一个对象相关的对象。

我有以下实体:

客户:

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

    public string ClientId { get; set; }

    public string ClientName { get; set; }

    public List<ClientScope> Scopes { get; set; }
}

客户范围:

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

    public string Scope { get; set; }

    public Client Client { get; set; }
  }

OnModelCreating:

modelBuilder.Entity<Client>((Action<EntityTypeBuilder<Client>>) (client =>
      {
        client.ToTable<Client>(storeOptions.Client);
        client.HasKey((Expression<Func<Client, object>>) (x => (object) x.Id));
        client.Property<string>((Expression<Func<Client, string>>) (x => x.ClientId)).HasMaxLength(200).IsRequired(true);
        client.HasIndex((Expression<Func<Client, object>>) (x => x.ClientId)).IsUnique(true);
        client.HasMany<ClientScope>((Expression<Func<Client, IEnumerable<ClientScope>>>) (x => x.AllowedScopes)).WithOne((Expression<Func<ClientScope, Client>>) (x => x.Client)).IsRequired(true).OnDelete(DeleteBehavior.Cascade);
      }));

modelBuilder.Entity<ClientScope>((Action<EntityTypeBuilder<ClientScope>>) (scope =>
      {
        scope.ToTable<ClientScope>(storeOptions.ClientScopes);
        scope.Property<string>((Expression<Func<ClientScope, string>>) (x => x.Scope)).HasMaxLength(200).IsRequired(true);
      }));

我想更新特定Client.IdClientScope ,例如 Id = 1。

我试过用这种方式:

public void UpdateClientScope(ClientScope scope){

_dbContext.ClientScope.Update(scope);
_dbContext.SaveChanges();
}

var scope = new ClientScope() { Client = new Client{Id = 1}, Id = 1, Scope = "Test Scope" }
UpdateClientScope(scope);

但是这种方式也尝试更新Client 我只想更新 ClientScope 并指定它存储在我的表单上的 ClientId。

如何更新上面的ClientScope的最佳方法是什么?

我试图实现BaseRepository ,我想为每个实体实现这样的东西:

public class BaseRepository<TDbContext, TEntity, TPrimaryKey> : IBaseRepository<TDbContext, TEntity, TPrimaryKey>
        where TEntity : class
        where TDbContext : DbContext
{
 public virtual DbSet<TEntity> Table => _dbContext.Set<TEntity>();

private readonly TDbContext _dbContext;

public BaseRepository(TDbContext dbContext)
        {
            _dbContext = dbContext;
        }

public virtual async Task<TEntity> UpdateAsync(TEntity entity)
        {
            Table.Update(entity);

            await _dbContext.SaveChangesAsync();

            return entity;
        }
}

但我不知道 - 如何正确地为这样的实体指定update方法?

谢谢你的任何建议。

如果您从不打算通过存储库方法添加或修改相关实体,您可以简单地将所有其他实体的状态设置为EntityState.Unchanged ,例如:

public virtual async Task<TEntity> UpdateAsync(TEntity entity)
{
    Table.Update(entity);

    foreach( var entry in _dbContext.ChangeTracker.Entries() )
    {
        if( entry.Entity != entity )
        {
            entry.State = EntityState.Unchanged;
        }
    }

    await _dbContext.SaveChangesAsync();

    return entity;
}

或者,在调用 repo 方法之前附加相关实体不变。 也许创建一个 repo 方法来返回这样的实体:

public TEntity GetEntityPlaceholder( int id )
{
    var entity = new TEntity() { Id = id };
    _dbContext.Attach( entity );
    return entity;
}

我更喜欢 FK 属性可用,我自己:

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

    public string Scope { get; set; }

    public Client Client { get; set; }
    // FK, use [ForeignKey( "Client" )] if you wish
    public int ClientId { get; set; }
}

// or use FluentAPI
modelBuilder.Entity<ClientScope>()
    .HasRequired( cs => cs.Client )
    .WithMany( c => c.Scopes )
    // specify foreign key
    .HasForeignKey( cs => cs.ClientId );

// now can specify a client by setting the ClientId property
var scope = new ClientScope() 
{ 
    ClientId = 1, 
    Id = 1, 
    Scope = "Test Scope",
}
UpdateClientScope(scope);

正如评论中提到的(谢谢,Ivan),EF 需要“了解”您要更新的对象。

抱歉,我没有任何可测试的东西,但您的 UpdateClientScope 方法应该如下所示:

public void UpdateClientScope(ClientScope scope){

// Get the existing object from the DB
ClientScope dbScope = _dbContext.ClientScope.FirstOrDefault(x => x.Id == scope.Id);

// Test it was in DB
if (dbScope != null)
{
  // Update the database object
  dbScope.Scope = scope.Scope;
  dbScope.Client = scope.Client;

  // SaveChanges works on dbScope
  _dbContext.SaveChanges();
}
else
{
  // Object not found, some error processing
}
}

我不明白是哪里出了问题? 通过 DBContext 对象,您可以访问任何类对象而不是对象的属性,而不仅仅是使用简单的赋值运算符更改属性值,而只是 DbContext.SaveChanges() 您的更改将在数据库列中更新,完全没有问题。 如果您想要单独的 Update() 方法进行更改,您可以使用几行代码或更复杂的方式来实现 C# 反射,但我无法想象您为什么需要这个?! 如果我错过了什么,请告诉我更多。 祝你好运!!!!

我认为您的实体是错误的,因为您的 ClientScope 没有 clientId(外键)。

公共字符串 ClientId { 获取; 设置; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM