Oracle 中使用复合主键更新多对多表

问题描述 投票:0回答:1

我有 2 个表,它们之间存在多对多关系。为了使这种多对多关系发挥作用,我创建了一个新表。这个多对多表只有其他 2 个表的 id:

id_table1
id_table2

我将数据存储在这个多对多表中,但我在向导中没有看到它,但它存在是因为我有

GetAll
API 和
GetById
API 正在运行。

如何更新此表?

public void Update(T_TPS_PARAMETERS model)
{
    _context = new CostingAppDb();

    try
    {
        T_TPS_PARAMETERS oldTpsParameters = _context.T_TPS_PARAMETERS.FirstOrDefault(c => c.TPS_ID == model.TPS_ID);
        decimal oldTpsParametersId = oldTpsParameters.TPS_ID;

        foreach (var company in model.T_COMPANY)
        {
            T_COMPANY oldCompany = _context.T_COMPANY.FirstOrDefault(c => c.ID_COMPANY == company.ID_COMPANY);
            decimal oldCompanyId = oldCompany.ID_COMPANY;

            UpdateRelationship(oldCompanyId, oldTpsParametersId, company.ID_COMPANY, model.TPS_ID);
        }

        _context.Entry(model).State = System.Data.Entity.EntityState.Modified;
        _context.SaveChanges();
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

private void InsertWithData(decimal companyId, decimal tpsId)
{
    T_COMPANY c = new T_COMPANY { ID_COMPANY = companyId };

    _context.T_COMPANY.Add(c);
    _context.T_COMPANY.Attach(c);

    T_TPS_PARAMETERS psd = new T_TPS_PARAMETERS { TPS_ID = tpsId };

    _context.T_TPS_PARAMETERS.Add(psd);
    _context.T_TPS_PARAMETERS.Attach(psd);

    c.T_TPS_PARAMETERS.Add(psd);

    _context.SaveChanges();
}

public void DeleteRelationship(decimal companyId, decimal tpsId)
{
    var company = _context.T_COMPANY.FirstOrDefault(c => c.ID_COMPANY == companyId);
    var tpsParameter = _context.T_TPS_PARAMETERS.FirstOrDefault(p => p.TPS_ID == tpsId);

    company.T_TPS_PARAMETERS.Remove(tpsParameter);

    _context.SaveChanges();
}

public void UpdateRelationship(decimal oldCompanyId, decimal oldTpsId, decimal newCompanyId, decimal newTpsId)
{
    DeleteRelationship(oldCompanyId, oldTpsId);
    InsertWithData(newCompanyId, newTpsId);
}

这是我得到的错误:

System.Data.Entity.Infrastruct.DbUpdateException:“保存未公开其关系的外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地处理保存时的异常。有关详细信息,请参阅 InnerException。'

InvalidOperationException:表/视图没有定义主键。该实体是只读的

c# asp.net oracle entity-framework many-to-many
1个回答
0
投票

使用EF,多对多连接表可以显式映射到实体,也可以隐式映射。在大多数情况下,如果连接表只是将两者链接起来,那么使用隐式映射会更简单。例如隐式映射:

public class A
{
    // ... 
    public virtual ICollection<B> Bs { get; } = [];
}

public class B
{
    // ...
    public virtual ICollection<A> As { get; } = [];
}

vs explicit:

public class A
{
    // ... 
    public virtual ICollection<AB> ABs { get; } = [];
}

public class B
{
    // ...
    public virtual ICollection<AB> ABs { get; } = [];
}

public class AB
{
    public virtual A A { get; set; }
    public virtual B B { get; set; }
}

删除关联时,无论哪种情况,您都可以通过关联的导航属性来执行此操作。在您的情况下,DeleteRelationship 方法应该类似于:

public void DeleteRelationship(decimal companyId, decimal tpsId)
{
    var company = _context.T_COMPANY
        .Include(c => c.TPS_PARAMETERS)
        .Single(c => c.ID_COMPANY == companyId);

    var tpsParameter = company.TPS_PARAMETERS.FirstOrDefault(p => p.TPS_ID == tpsId);
    if (tpsParameter != null)
    {
        company.T_TPS_PARAMETERS.Remove(tpsParameter);
        _context.SaveChanges();
    }
}

如果您在提取中添加

.Include(c => c.TPS_PARAMETERS)
,那么您的代码也会起作用,前提是从数据库提取的参数位于公司的参数列表中。

每当从一对多或多对多的关联中添加或删除项目时,您应该始终确保相关实体已加载。这样,EF 就可以利用更改跟踪代理来确定添加或删除关联时要执行的操作。

© www.soinside.com 2019 - 2024. All rights reserved.