nhibernate - sproutcore:如何只检索参考 ID 而不加载参考/关系?

Posted

技术标签:

【中文标题】nhibernate - sproutcore:如何只检索参考 ID 而不加载参考/关系?【英文标题】:nhibernate - sproutcore : How to only retrieve reference ID's and not load the reference/relation? 【发布时间】:2010-10-11 09:21:58 【问题描述】:

我使用作为前端的 sproutcore,作为后端使用 nhibernate 驱动的 openrasta REST 解决方案。

在sproutcore 中,引用实际上是ID/guid。因此,Sproutcore 模型中的地址实体可能是:

// sproutcore code

App.Address = App.Base.extend(

street: SC.Record.attr(String, defaultValue: "" ),

houseNumber: SC.Record.attr(String),

city: SC.Record.toOne('Funda.City')

);

有测试数据:

Funda.Address.FIXTURES = [

guid: "1",

street: "MyHomeStreet",

houseNumber: "34",

city: "6"

]

在这里,您看到参考城市的值为 6。当您在程序中的某个时刻想要使用该参考时,可以通过以下方式完成: myAddress.Get("city").MyCityName

因此,Sproutcore 会自动在 REST Get 中使用提供的 ID,并检索所需的记录。如果记录在客户端的本地内存中可用(之前已加载),则不会对服务器进行往返,否则会对该 ID 进行 http get:“http://servername/city/6”。很不错。

Nhibernate(使用 fluent-nhibernate 映射):

public AddressMap() Schema(Config.ConfigElement("nh_default_schema", "Funda"));

        Not.LazyLoad();

        //Cache.ReadWrite();

        Id(x => x.guid).Unique().GeneratedBy.Identity();  

        Table("Address");

        Map(x => x.street);

        Map(x => x.houseNumber);

        References(x => x.city,   

"cityID").LazyLoad().ForeignKey("fk_Address_cityID_City_guid");

这里我指定了外键,并将“cityID”映射到数据库表上。它工作正常。 但是(这些是我对大师的问题):

    您可以指定延迟加载/急切加载引用(城市)。当然,您不想急切地加载所有参考资料。所以通常你与延迟加载有关。 但是当 Openrast(或 WCF 或 ...)序列化这样的对象时,它会迭代属性,这会导致属性的所有 get 被触发,这会导致所有引用都被延迟加载。

所以如果您的实体有 5 个引用,1 个基本对象查询和 5 个引用将被完成。那么你最好不要急于加载...... 这太糟糕了......还是我错了?

    当我展示了 sproutcore 中的模型如何工作时,我只想要引用的 ID。所以我不想急切加载,也不想延迟加载。 只是一个“从 ID = % 的地址获取 *”并将其映射到我的地址实体。 那么我也有让 Sproutcore 和我高兴的参考 ID(不加载不需要的参考)。但是.... NHibernate 可以仅映射引用的 ID 吗? 我以后可以指示 nHibernate 完全加载引用吗?

一种方法可能是(但不是一个好方法)加载所有引用 EAGER(加入)(多么浪费资源……我知道)并在我的服务器端地址实体中:

    // Note: NOT mapped as Datamember, is NOT serialized!

    public virtual City city  get; set; 

    Int32 _cityID;
    [Datamember]
    public virtual Int32 cityID
    
        get
        
            if (city != null)
                return city .guid;
            else
                return _cityID;
        
        set
        
            if (city!= null && city.guid != value)
            
                city= null;
                _cityID = value;
            
            else if (city == null)
            
                _cityID = value;
            
        
    

所以我获得了 Sproutcore 的 ID 属性,但不利的一面是,所有引用都已加载。 对我来说更好的主意???

    nHibernate-to-linq

3a。我想在没有他们的参考资料的情况下获得我的地址(但最好有他们的 id)

道 myDao = new Dao(); 来自 myDao.All() 中的 p 选择 p;

如果城市在我的映射中延迟加载,我如何在 linq 查询中指定我希望它也只包含我的城市 ID?

3b.

我想获取我的城市在 1 个查询中加载的地址:(映射为延迟加载)

道 myDao = new Dao(); 来自 myDao.All() 中的 p 加入p.city ??????? 选择 p;

    我的主要问题: 如前所述,通过延迟加载,在序列化实体时所有引用都是延迟加载的。我怎样才能防止这种情况,并且只能以更有效的方式获取参考 ID?

非常感谢您的阅读,希望您能帮助我和其他有相同问题的人。亲切的问候。

【问题讨论】:

【参考方案1】:

作为你写的笔记,你这样做

myAddress.Get("city").MyCityName

应该是什么时候

myAddress.get("city").get("MyCityName")

myAddress.getPath("city.MyCityName")

除此之外,我认为您的问题是“我要如何才能不加载城市对象?”。

假设您正在使用数据源,当您请求城市对象时,您需要在数据源中进行管理。因此,在您的数据源中的retrieveRecord 中根本不触发请求,并使用适当的参数调用dataSourceDidComplete(查看datasource.js 文件),因此城市记录不在BUSY 状态。您基本上是在告诉商店记录已加载,但您传递了一个空哈希,因此该记录没有数据。

当然,问题在于您有时需要检索记录。您可以定义一个像App.WANTS_CITY 这样的全局变量,并且在retrieveRecords 中仅在您需要城市时进行检索。您需要管理该触发器的值;状态图是执行此操作的好地方。

您问题的另一部分是“我如何一次加载一堆记录,而不是每条记录一个请求?

注意数据源有一个方法retrieveRecords。您可以为该方法定义自己的实现,这将允许您获取所需的任何记录——这避免了对 N 个子记录的 N 次请求——你可以在一个请求中完成所有这些。

最后,就我个人而言,我倾向于使用诸如

之类的方法编写 API 层

getAddressgetCity

并在我真正需要对象时适当地调用我的 API。这种方法的一部分是我有一个非常轻量级的数据源——我基本上摆脱了所有创建/更新/获取方法,具体取决于我的 API 层处理的内容。我使用pushRetrieve 和相关方法来更新商店。

我这样做是因为商店以非常严格的方式在数据源中使用。我喜欢更多的灵活性;并非所有服务器 API 都以相同的方式工作。

【讨论】:

以上是关于nhibernate - sproutcore:如何只检索参考 ID 而不加载参考/关系?的主要内容,如果未能解决你的问题,请参考以下文章

SproutCore 以编程方式触发 MenuPane 中的项目选择

Nhibernate 如何处理插入、更新、删除

Nhibernate:如何用一对多关系表示多对多关系?

Nhibernate 与其他 ORM 的区别是啥?

NHibernate 中的 Lazy 是啥意思

如何绕过 NHibernate 版本控制更新 SQL 中的记录