代码之家  ›  专栏  ›  技术社区  ›  Spoike Otávio Décio

如何使用来自不同数据上下文的对象处理提交?

  •  0
  • Spoike Otávio Décio  · 技术社区  · 16 年前

    我遇到了一个问题,即使用来自同一类型的两个数据上下文的对象将无法在上提交对象。为了简单起见,考虑下面的Linq to SQL设计,其中我们有描述汽车和人员的数据库表。

    +--------------+         +--------+
    | Car          | 1     1 | Person |
    +--------------+---------+--------+
    | Registration |         | name   |
    | ownerId {FK} |         +--------+
    +--------------+
    

    然后,我们有两个数据存储库,其中一个实例指向同一个DataContext类,具有以下方法:

    public OwnerRepository {
        private MyDataContext db;
    
        public Person GetOwnerByName(string ownerName)
        {
            return (from person in db.Persons
                   where person.Name == ownerName
                   select person).SingleOrDefault();
        }
    }
    
    public CarRepository {
        private MyDataContext db;
    
        public Car GetCarByRegistration(string registration)
        {
            return (from car in db.Cars 
                   where car.Registration == registration
                   select car).SingleOrDefault();
        }
    
        public void RegisterOwner(Person owner, string registration)
        {
            var car = GetCarByRegistration(registration);
            car.Owner = owner;
            db.SubmitChanges();
        }
    }
    

    假设我们从车主存储库中找到一个人,并使用它将该人注册为汽车车主:

    var owner = ownerRepository.GetOwnerByName("Peter Pan");
    carRepository.RegisterOwner(owner, "TOO COOL");
    

    方法 RegisterOwner 将引发异常,因为DataContext无法识别Person对象(即使它是同一类型)。你能做些什么来解决这个问题?

    2 回复  |  直到 16 年前
        1
  •  1
  •   eglasius    16 年前

    Linq2SQL不支持直接使用跨数据上下文对象-序列化/反序列化/附加确实不值得。

    您所拥有的场景是存储库之间耦合的结果。您正在使用同一个DataContext类创建对它的内部依赖项,该类在尝试直接使用接收的实体的RegisterOwner代码上显示。

    考虑一下,如果调用代码更新了Person实体上的某些内容,那么注册所有者的代码是否真的要保存这些更改?

    在同一个有界上下文中,存储库级别的这种耦合可能是正常的。如果这些子系统是独立的子系统,那么汽车存储库将只保存它要处理的信息,这是所有者信息的一个子集,用于标识汽车系统中的用户。这就是让你一路切换的原因。当然,在更复杂的场景中,如果你想有更高的分离度,这就更有意义了。

    请注意,在发布的示例中,您实际上不需要更新任何关于Person的内容,因此您可以有效地使用仅在车主信息上设置Person ID的版本,而不是为其分配完整的Person实例。

    对于更耦合的场景,您可以使用jon的答案-为他们提供相同的DataContext实例。

        2
  •  2
  •   Jon Skeet    16 年前

    你为什么有两个不同的 DataContexts 首先呢?听起来是个坏主意。为什么不给 CarRepository 在其中传递 DataContext ?然后两个存储库可以使用相同的 数据上下文 .

    使用单一 数据上下文 意味着提交可以作为一个事务进行,并且在上下文中的缓存对数据库中的内容有不同的想法时,不会出现奇怪的问题。