2

希望有人可以帮助我更多地了解 .net 核心实体框架在以下场景中的工作原理。

我有一个更新功能,它工作得很好。
但是当我尝试优化我的选择查询时,我遇到了一个错误。为了更好地理解,这里有 3 个类及其所涉及的关系:

public class Dealer
{
    public int Id { get; set; }
    public string Name { get; set; }
    ...
    public virtual ICollection<Vehicle> Vehicles { get; set; }
}

public class Vehicle
{
    public string Id { get; set; }
    public string Brand { get; set; }
    public string Model { get; set; }
    ...
    public int DealerId { get; set; }
    public Dealer Dealer { get; set; }
    public virtual ICollection<Accessory> Accessories { get; set; }
}

public class Accessory
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Quantity { get; set; }
    public string VehicleId { get; set; }
    public Vehicle Vehicle { get; set; }
}

这是我更新数据的功能。

public void DoSomething()
{
    var dealer = _dealerService.Get(123);
    ... // some dealer field value changes

    var vehicle = new Vehicle { ... };
    vehicle.Id = Guid.NewGuid().ToString();
    vehicle.Accessories.Add(new Accessory { ... });
    dealer.Vehicles.Add(new List<Vehicle> { vehicle });

    _dealerService.Update(dealer);
}

工作版本只是一个简单的选择方法,默认情况下为经销商获取每个字段:

public Dealer Get(int id)
{
    return _db.Where(x => x.Id == id).FirstOrDefault();
}

根据日志,可以看出魔法按以下顺序发生:

  1. 插入 [车辆]
  2. 更新 [经销商]
  3. 插入 [附件]

现在我正在尝试优化速度,因为 Dealer 有很多字段,所以我决定只选择 Dealer 所需的字段,以便查询花费更短的时间。因此,我像这样更新了方法

public Dealer Get(int id)
{
    return _db.Where(x => x.Id == id)
        .Select(x => new Dealer 
        {
            Id = x.Id,
            Name = x.Name,
            ...
        })
        .FirstOrDefault();
}

那时我遇到了这个错误 SqlException:INSERT 语句与 FOREIGN KEY 约束“FK_Accessories_Vehicles_Id”冲突。冲突发生在数据库、表“dbo.Vehicles”、“Id”列中。

INSERT INTO [Accessories] ([Name], [Quantity], [VehicleId])  
VALUES (@p0, @p1, @p2);  
SELECT [Id] FROM [Accessories] WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity(); 

从日志中很明显,为什么它首先尝试插入 [附件] 而不是第三步的工作版本。

所以在这里我希望有人可以解释为什么通过为我的选择查询指定特定字段会导致这样的行为,即当涉及 FK 时,.net 首先插入附件而不是车辆。

提前致谢。

4

0 回答 0