2013-02-10 23 views
5

Tôi có một ứng dụng SPA (durandaljs) và tôi có một tuyến đường cụ thể nơi tôi lập bản đồ "id" của thực thể mà tôi muốn tìm nạp.Breezejs EntityManager MetadataStore và fetchEntityByKey

Mẫu là "/ #/todoDetail /: id".

Ví dụ: "/ #/todoDetail/232" hoặc "/ #/todoDetail/19".

Bật chức năng kích hoạt của chế độ xem, tôi nhận thông tin tuyến đường để tôi có thể lấy id. Sau đó, tôi tạo một thể hiện mới của breezejs EntityManager để lấy thực thể với id đã cho.

Vấn đề là khi tôi gọi manager.fetchEntityByKey ("Todos", id), EntityManager chưa có siêu dữ liệu từ máy chủ, do đó, nó ném ngoại lệ "Không thể định vị 'Loại' theo tên: Todos ".

Nó chỉ hoạt động nếu trước tiên tôi thực hiện truy vấn đối với cửa hàng (manager.executeQuery), trước khi gọi hàm fetchEntityByKey.

Đây có phải là hành vi dự kiến ​​hoặc lỗi không? Có cách nào để tự động fecth siêu dữ liệu trong instantiation EntityManager?

lưu ý: Tôi tin rằng thật khó để sử dụng EntityManager được chia sẻ trong trường hợp của tôi, vì tôi muốn cho phép người dùng trực tiếp nhập tuyến đường trên trình duyệt.

EDIT: Là một workaround tạm thời, tôi đang làm điều này:

BreezeService.prototype.get = function (id, callback) { 
    var self = this; 

    function queryFailed(error) { 
     app.showMessage(error.message); 
     callback({}); 
    } 

    /* first checking if metadatastore was already loaded */ 

    if (self.manager.metadataStore.isEmpty()) { 
     return self.manager.fetchMetadata() 
     .then(function (rawMetadata) { 
      return executeQuery(); 
     }).fail(queryFailed); 
    } else { 
     return executeQuery(); 
    } 

    /* Now I can fetch */ 
    function executeQuery() { 
     return self.manager.fetchEntityByKey(self.entityType, id, true) 
         .then(callback) 
         .fail(queryFailed); 
    } 
}; 

Trả lời

7

Bạn đã biết về fetchMetadata. Đó là quan trọng. Nếu ứng dụng của bạn có thể bắt đầu mà không đưa ra truy vấn, bạn phải sử dụng fetchMetadata và đợi nó quay trở lại trước khi bạn có thể thực hiện bất kỳ thao tác nào trực tiếp trên bộ đệm (ví dụ: kiểm tra thực thể bằng khóa trong bộ nhớ cache trước khi quay trở lại truy vấn cơ sở dữ liệu).

Nhưng tôi cảm thấy điều gì đó đang diễn ra vì bạn đã đề cập đến nhiều người quản lý. Theo mặc định, người quản lý mới không biết siêu dữ liệu từ bất kỳ người quản lý nào khác. Nhưng bạn có biết rằng bạn có thể chia sẻ một siêu dữ liệu duy nhất trong số các nhà quản lý không? Bạn có thể.

Những gì tôi thường làm (và bạn sẽ thấy nó trong các thử nghiệm siêu dữ liệu trong mẫu DocCode), lấy một siêu dữ liệuStore cho ứng dụng, viết một chức năng nhà máy EntityManager để tạo người quản lý mới với siêu dữ liệu đó rồi sử dụng nhà máy bất cứ khi nào tôi làm cho các nhà quản lý mới ... như bạn dường như đang làm khi bạn quay lên một ViewModel để xem lại TodoDetail.

+0

sugestion tốt, vì vậy tôi sẽ tạo entityManagers với các nhà máy, chia sẻ siêu dữ liệu toàn cầu giữa chúng. Nhân tiện, liệu có cơ hội nào để cải thiện làn gió để thêm cơ sở này, giống như một trường hợp toàn cầu của metadatastore? Hoặc sau đó buộc thực thể truy vấn siêu dữ liệu ngay cả khi tôi chỉ muốn fetchEntityByKey, mà không cần chạy truy vấn đầy đủ đối với dịch vụ? –

+0

Không chắc chắn ý bạn là gì. Tôi không quan tâm đến MetadataStore mặc định của Breeze nhưng đó là thứ bạn có thể dễ dàng tạo cho chính mình. Bạn có thể yêu cầu một MetadataStore để fetchMetadata (đó là không đồng bộ của khóa học) khá ngoài một truy vấn (tôi đã đề cập đến điều này trong câu trả lời của tôi). Bạn cũng có thể nhìn vào 'EntityManager.createEmptyCopy'. Bạn có thể gọi nó trên EM chủ của bạn để tạo các EM trống mới được cấu hình đầy đủ; phần còn lại của phương thức factory sẽ nhập từ master chỉ những thực thể đó (ví dụ: danh sách tham chiếu) mà bạn muốn trong bản sao. – Ward

2

Đến từ nền Silverlight, nơi tôi đã sử dụng rất nhiều Dịch vụ RIA của WCF kết hợp với Caliburn Micro, tôi đã sử dụng phương pháp này để tích hợp Breeze với Durandal.

Tôi đã tạo thư mục con được gọi là dịch vụ trong thư mục Ứng dụng của ứng dụng. Trong thư mục đó, tôi đã tạo một tệp javascript có tên datacontext.js. Dưới đây là một tập hợp con của đoạn mã dữ liệu của tôi:

define(function (require) { 

    var breeze = require('lib/breeze'); // path to breeze 
    var app = require('durandal/app'); // path to durandal 

    breeze.NamingConvention.camelCase.setAsDefault(); 

    // service name is route to the Web API controller 
    var serviceName = 'api/TeamData', 

    // manager is the service gateway and cache holder 
    manager = new breeze.EntityManager(serviceName), 

    store = manager.metadataStore; 

    function queryFailed(error) { 
     app.showMessage("Query failed: " + error.message); 
    } 

    // constructor overrides here 

    // included one example query here 
    return datacontext = { 
     getSponsors: function (queryCompleted) { 
      var query = breeze.EntityQuery.from("Sponsors"); 
      return manager 
       .executeQuery(query) 
       .then(queryCompleted) 
       .fail(queryFailed) 
     } 
    }; 
} 

Sau đó, trong các kiểu xem sầu riêng, bạn chỉ có thể yêu cầu dịch vụ/datacontext.Ví dụ: đây là một phần của mô hình chế độ xem mẫu từ ứng dụng của tôi:

define(function (require) { 

    var datacontext = require('services/datacontext'); 

    var ctor = function() { 
     this.displayName = 'Sponsors', 
     this.sponsors = ko.observable(false) 
    }; 

    ctor.prototype.activate = function() { 
     var that = this; 
     return datacontext.getSponsors(function (data) { that.sponsors(data.results) }); 
    } 

    return ctor; 
}); 

Điều này sẽ cho phép bạn không lo lắng về việc khởi tạo siêu dữ liệu trong mọi mô hình xem vì tất cả được thực hiện ở một nơi.

+0

Tôi cũng có một nền tảng về Silverlight/Caliburn.Micro và WCF Ria Services. Trên thực tế, nếu bạn đang sử dụng Gói từ MVC, bạn có thể đưa breeze.min.js vào các tập lệnh được nhóm và bạn không cần phải gọi ('path/to/breeze'). Xem [video cố định] của tôi (http://www.youtube.com/watch?feature=player_embedded&v=in1M0vzg4mg). Vấn đề của tôi là tôi muốn siêu dữ liệu mà không làm một truy vấn đầu tiên. Cảm ơn! –

+0

Tôi đoán nó làm việc cho tôi bởi vì tôi đã sử dụng một truy vấn để có được thực thể duy nhất. var query = breeze.EntityQuery.from ("AthleteDetails"). where ("Id", "==", id); – Bryant

+0

có, đã làm việc vì nếu bạn sử dụng EntityQuery, bạn đang chạy truy vấn sẽ tìm nạp siêu dữ liệu nếu người quản lý chưa tìm nạp trước ... kết quả truy vấn sẽ là một mảng các thực thể, vì vậy bạn cần truy cập nó bằng chỉ mục 0 như result.entities [0]. Nó không phải là trường hợp fetchEntityByKey() luôn trả về một thực thể hoặc null và có thể trả về thực thể từ bộ nhớ cache nếu muốn, nhưng nó sẽ không tìm nạp siêu dữ liệu cho người quản lý và sẽ ném ngoại lệ nếu tôi không tìm nạp thủ công, như tôi đã làm trong câu hỏi. –

Các vấn đề liên quan