如何在插入/更新时仅使用外表的 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
步骤如下:
- 在数据库中查找客户
- 它不存在? --> 创建记录
- 客户所在城市是否与传入数据(城市)相同?如果是,请转到步骤 (8)
- 检查缓存,如果我们有适当的城市,如果是,请转到 (7)
- 创建城市记录
- 拯救城市
- 绑定城市和客户
- 拯救客户
因此,在 (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 之间)。
你试过吗
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();
}