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

时间:2011-05-19 08:26:11

标签: c# linq-to-sql

我的程序比较复杂,但基本上问题就是这样 - 有表Customer和table City。在Customor中我有字段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;

加上类似的财产。

2

我发现这是由于获取数据。加载数据后(在这种情况下为客户提供城市对象),Linq To SQL假定它是固定,即id和city引用必须同步。如果在更改它们之前没有读取它们就可以了,因为L2S设置了新值,但也可以在运行中从DB中获取新数据。

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

3

步骤如下:

  1. 在DB中找到客户
  2. 它不存在? - &GT;创建记录
  3. 客户所在城市与传入数据(城市)相同?如果是,请转到步骤(8)
  4. 检查缓存是否有合适的城市,如果是,请转到(7)
  5. 创建城市记录
  6. 拯救城市
  7. 绑定城市和客户
  8. 节省客户
  9. 因此在(3)中读取了客户的城市字段,在(7)中,要么抱怨使用来自其他上下文的数据,要么是不同步的字段(数据更改时的情况)。

    为了进行比较,我使用Entity Framework测试了几个案例,它表现得更直接,即两种方法都没有问题(当用整个对象或只是id更改引用字段时)。

    4

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

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

1 个答案:

答案 0 :(得分:0)

你试过吗

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