简体   繁体   English

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

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

I have used the Entity Framework Core and update some object with relation to another object.我使用了Entity Framework Core并更新了一些与另一个对象相关的对象。

I have a following entities:我有以下实体:

Client:客户:

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

    public string ClientId { get; set; }

    public string ClientName { get; set; }

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

ClientScope:客户范围:

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

    public string Scope { get; set; }

    public Client Client { get; set; }
  }

OnModelCreating: 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);
      }));

I would like update the ClientScope for specific Client.Id for example Id = 1.我想更新特定Client.IdClientScope ,例如 Id = 1。

I have tried use this way:我试过用这种方式:

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);

But this way try to update the Client as well.但是这种方式也尝试更新Client I want to update only ClientScope and specify ClientId which it is stored on my form.我只想更新 ClientScope 并指定它存储在我的表单上的 ClientId。

What is the best way how update ClientScope above?如何更新上面的ClientScope的最佳方法是什么?

I have tried to implement the BaseRepository which I want to implement for every entity something like this:我试图实现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;
        }
}

But I don't know - How correctly specify the update method for entities like this?但我不知道 - 如何正确地为这样的实体指定update方法?

Thank you for any suggestion.谢谢你的任何建议。

If you never plan to add or modify a related entity via your repository methods you can simply set all other entities' state to EntityState.Unchanged , eg:如果您从不打算通过存储库方法添加或修改相关实体,您可以简单地将所有其他实体的状态设置为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;
}

Alternatively, attach related entities as unchanged before calling the repo method(s).或者,在调用 repo 方法之前附加相关实体不变。 Perhaps create a repo method to return such an entity:也许创建一个 repo 方法来返回这样的实体:

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

I prefer having the FK properties available, myself:我更喜欢 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);

As mentioned in the comments (thanks, Ivan), EF needs to 'know about' the object you want to update.正如评论中提到的(谢谢,Ivan),EF 需要“了解”您要更新的对象。

Sorry, I don't have anything to hand to test this with, but your UpdateClientScope method should look something like this:抱歉,我没有任何可测试的东西,但您的 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
}
}

I do not understand where is a problem ?我不明白是哪里出了问题? through DBContext object you can reach any class object than object's property, than just change a value of property with simple assign operator and just DbContext.SaveChanges() your changes will be updated in Database column with no problem at all.通过 DBContext 对象,您可以访问任何类对象而不是对象的属性,而不仅仅是使用简单的赋值运算符更改属性值,而只是 DbContext.SaveChanges() 您的更改将在数据库列中更新,完全没有问题。 If you want separate Update() method for changes you can do it with couple of code lines or more complex way with C# Reflection possibility but i can't imagine why would you need this ?!如果您想要单独的 Update() 方法进行更改,您可以使用几行代码或更复杂的方式来实现 C# 反射,但我无法想象您为什么需要这个?! If i missed something tell me more.如果我错过了什么,请告诉我更多。 Good luck !!!!祝你好运!!!!

i think your entities false because your ClientScope has not clientId (Foreign Key).我认为您的实体是错误的,因为您的 ClientScope 没有 clientId(外键)。

public string ClientId { get;公共字符串 ClientId { 获取; set;设置; } }

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

相关问题 EntityFramework与复合键的核心关系 - EntityFramework Core relation to composite key 如何使用 EntityFramework Core 在两个模块之间创建关系? - How to create a relation between two modules using EntityFramework Core? 如何更新EntityFramework Core Code First对象,包括所有也是复杂对象的属性? - How to update EntityFramework Core Code First object including all properties which are also complex objects? C#EntityFramework Core-无效的对象名称,无法更新数据库 - C# EntityFramework Core - Invalid object name, cannot update database EntityFramework 核心 - 在不选择实体的情况下更新数据集合 - EntityFramework core - Update a collection of data without selecting the entities 如何使EntityFramework Relation IQueryable? - How to make EntityFramework Relation IQueryable? 如何在EntityFramework 6中更新带有子详细信息的父对象? - How can I update a parent object that comes with child details in EntityFramework 6? 如何使用具有多对多关系的EntityFramework执行查询 - How to execute a query with EntityFramework with relation many to many 具有一对多关系的 EntityFramework Core 总是返回一个空集合 - EntityFramework Core with one-to-many relation always returns an empty collection 如何使用EntityFramework核心将实体单数化 - How to singularize entities with EntityFramework core
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM