如何在插入/更新时仅使用外表的 ID 而不是完整对象

本文关键字:ID 对象 插入 更新 | 更新日期: 2023-09-27 17:57:11

我的程序比较复杂,但基本上问题是这样的——有表客户和表城市。在自定义器中,我有字段 cityId 和外键。

现在我可以写这样的代码了

customer.cityIdCity = myCity;

customer.cityId = 7;

问题是我不能使用第一种形式,因为城市是缓存的,在这种情况下,数据将被当前数据上下文"劫持"(并且会发生异常),所以我更喜欢使用第二种形式。但是,当我为客户提交更改时,我收到有关数据不一致的异常 - 老实说这是真的 - cityId 是 7,但 cityIdCity 是空的。

问题是 - 对于第二种形式,如何强制 LINQ 专注于 id(并使用 id 执行简单的插入),并接受丢失的对象。

编辑

1

字段 cityId 只是一个 int(如表中所示),但 sqlmetal 还为映射类 cityIdCity 创建了另一个属性,该属性引用了 City 类(来自表 City)。

内部看起来像这样:

    private EntityRef<City> _cityIdCity;

还有一个长属性 cityIdCity,它设置上述字段并处理事件触发以更改和更改字段的状态。

常规字段 (int) 定义如下:

    private System.Nullable<int> _cityId;

加上类似的属性。

阿拉伯数字

我发现这是由于获取数据。加载数据(在本例中为客户的城市对象)后,Linq To SQL 假定它是固定的,即 id 和城市引用必须同步。如果您在更改它们之前不读取它们,那没关系,因为 L2S 会设置新值,但也会动态从数据库获取新数据。

在更改之前,我必须阅读客户城市。

3

步骤如下:

  1. 在数据库中查找客户
  2. 它不存在? --> 创建记录
  3. 客户所在城市是否与传入数据(城市)相同?如果是,请转到步骤 (8)
  4. 检查缓存,如果我们有适当的城市,如果是,请转到 (7)
  5. 创建城市记录
  6. 拯救城市
  7. 绑定城市和客户
  8. 拯救客户

因此,在 (3) 中读取了客户的城市字段,而在 (7) 中,要么抱怨使用来自另一个上下文的数据,要么抱怨字段不同步(数据更改的情况)。

为了进行比较,我使用实体框架测试了几种情况,它的行为更加简单,即两种方法都没有问题(当使用整个对象或仅 id 更改引用字段时)。

这是简化的代码,但显示了问题。

using (var Db = new L2S.DataClasses1DataContext())
{
    var customer = Db.Customers.Single(it => it.cust_Id==2);
    customer.Name = "New name";
    Console.WriteLine(customer.City.city_Name); // loading city from DB
    // cannot change, because we would be out of sync with referenced object
    customer.city_Id = 57834; 
                            
    Db.SubmitChanges();
}

5 -- 瘦数据与胖数据上下文

使用与 Pleun 相同的示例。这是胖DC:

using (var Db = new L2S.DataClasses1DataContext())
{    
   ...
   customer.City = Db.Cities.Single (i=> i.id =   57834 ); 
   Db.SubmitChanges();
 }

因为如您所见,客户使用与城市相同的 DC(城市被缓存!这是错误的,因为来自客户的每个格式不正确的数据都会蔓延到 DC(缓存)。因此,一个小时前的错误现在也会出现。

这是薄 DC:

var city = CacheDb.Cities.Single (i=> i.id =   57834 ); 
...
using (var Db = new L2S.DataClasses1DataContext())
{    
   ...
   customer.City = city; 
   Db.SubmitChanges();
 }

但是,这不起作用,因为 L2S 不允许在 DC 之间共享实体(在典型情况下,在缓存和工作 - 更新 - DC 之间)。

如何在插入/更新时仅使用外表的 ID 而不是完整对象

你试过吗

using (var Db = new L2S.DataClasses1DataContext())
{    
 ...
 // leave out customer.city_Id = 57834;  but replace with
 customer.City = Db.Cities.Single (i=> i.id =   57834 ); 
 Db.SubmitChanges();
 }