【问题标题】:db4o Impedance Mismatchdb4o 阻抗不匹配
【发布时间】:2011-03-14 20:27:51
【问题描述】:

我围绕 db4o 数据库构建了一个不错的存储库层来存储 Product 对象,这些对象与 Manufacturer 对象以一对多的关系相关,即:

public class Manufacturer
{
    public string Name { get; set; }
}

public class Product // simplified
{
    public string Name { get; set; }
    Manufacturer Manufacturer { get; set; }
}

到目前为止,我真的很喜欢 db4o。我遇到的问题是在不借助 ID 的情况下防止数据重复。

当使用 SQL Server 实现制造商等引用时,我的数据模型将包含一个唯一的 ID 字段,而我的 Product 类又会被 ManufacturerID 弄脏。我以为使用像 db4o 这样的对象数据库会减少关系数据库和对象之间的阻抗不匹配,但是如果没有 ID,在编辑对象时就无法区分一个对象。

有没有一种优雅的方法可以在产品之间共享制造商而不复制数据?还是我应该只使用关系数据库?

【问题讨论】:

    标签: db4o duplication


    【解决方案1】:

    您可以在配置中为 db4o 添加唯一索引。

    configuration.Common.ObjectClass(typeof (Manufacturer)).ObjectField("<Name>k__BackingField").Indexed(true);
    configuration.Add(new UniqueFieldValueConstraint(typeof(Manufacturer), "<Name>k__BackingField"));
    

    这样,您的数据库中不可能有两个具有相同名称的不同制造商对象。字段名称必须是“k__BackingField”,因为您使用的是自动属性。当然,您可以添加一个整数 ID,并以相同的方式对其进行索引。

    【讨论】:

    • 不使用名称字段的自动属性以避免支持字段命名问题是否值得?
    • 如果您不想在以后为您的属性添加任何逻辑/检查,您可以使用自动属性。但是,如果您添加一些检查,则无论如何您都需要一个支持字段。如果您使用自动属性填充了数据库,则必须添加一些额外的配置以将支持字段重定向到数据库中的现有字段。例如:configuration.Common.ObjectClass(typeof (Manufacturer)).ObjectField("_name").Rename("k__BackingField");所以这取决于你;)
    【解决方案2】:

    首先是基本的东西。 db4o 通过their object-identity 管理对象。当您再次存储相同的对象实例时,db4o 将更新数据库中的该对象。这同样适用于参考。当两个不同的对象引用同一个对象时,它们实际上将引用数据库中的同一个对象。在您的示例中:当两个不同的产品引用同一个制造商实例时,它们也将引用数据库中的同一个制造商。这是通过在keeps track of the objects 的背景中有一个表来实现的。

    现在这种方法存在问题。一旦您序列化对象(Web 应用程序、Web 服务等)或关闭对象容器,db4o 就会忘记内存中的哪个对象属于哪个对象。然后它不再识别现有对象,只是将其存储为新对象。这意味着您永远不应加载和存储具有不同对象容器实例的对象。你可能需要IDs to recognizes objects。例如,跨网络请求识别对象。一个简单的解决方案是使用 Guid 为对象提供唯一的 id。

    回到你的问题。要在产品之间共享制造商,您只需将其指向同一制造商。像这样:

    Product newShinyProduct = new Product(); // the new thing
    // Get a existing product or manufacturerer, doesn't matter
    Product oldProduct = (from p in container.AsQueryable<Product>()
                         where p.Name == "Get a product"
                         select p).First();
    
    // now just assigne the existing manufacturer to the new product
    // this product will now refer to the same manufacturer
    // and db4o will store this that way. The manufacturer isn't doublicated.
    newShinyProduct.Manufacturer = oldProduct.Manufacturer;
    // store the new product in the database.
    container.Store(newShinyProduct);
    

    【讨论】:

      【解决方案3】:
      猜你喜欢
      • 2019-01-27
      • 2010-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-11
      • 1970-01-01
      相关资源
      最近更新 更多