【问题标题】:How to properly create a new Producer?如何正确创建新的Producer?
【发布时间】:2014-01-16 21:07:44
【问题描述】:

我正在使用驱动对象模型工具CodeFluentEntities 将模型部署到数据库引擎。

我正在考虑使用 localStorage 数据库引擎(如 IndexedDB 或 Web SQL)来为没有服务器的 Web 应用程序存储我的数据。

我查看了documentation,但在我看来有点差......我想我理解了Produce()Terminate()等注入点的基本原理,但是实际的目标目录呢?生产?

在我的情况下,这是 Javascript 源代码文件,我如何才能正确(以引用的方式)指定在哪里生成它们?它必须在一个外部项目中,还是我可以在另一个项目中填写一个目录(例如,我的 webapp 的 .vsproj)?

文档是否可以集成有关这方面的代码示例,或者有人可以将我重定向到适合我需要的文章?

【问题讨论】:

    标签: javascript sql local-storage producer codefluent


    【解决方案1】:

    模板方法

    根据您的需要,我建议您使用模板而不是开发您的自定义 Producer,其中包括部署原因。使用模板生成器(随 CodeFluent Entities 提供),您可以利用 CodeFluent Entities 元模型快速轻松地创建复杂的脚本。

    此生产者基于 CodeFluent Entities 的模板引擎,允许您在生产时生成文本文件(在您的情况下为 JavaScript)。 提醒一下,模板只是文本块和可以生成输出文件的控制逻辑的混合体

    此生产者负责所有常见操作:更新项目 (.XXproj) 以添加您生成的文件、添加缺失的引用等。 此后您可以找到一个基于 CodeFluent 实体模型生成 IndexDB 脚本文件的示例(仅用于演示目的)。这是模板源文件:

    [%@ reference name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll" %]
    [%@ namespace name="System" %]
    [%@ namespace name="System.Linq" %]
    [%@ namespace name="CodeFluent.Model" %]
    
    var context = {};
    context.indexedDB = {};
    context.indexedDB.db = null;
    
    context.indexedDB.open = function () {
        var version = 11;
        var request = indexedDB.open([%=Producer.Project.DefaultNamespace%], version);
    
        request.onupgradeneeded = function (e) {
            var db = e.target.result;
            e.target.transaction.onerror = context.indexedDB.onerror;
            [%foreach(Entity entity in Producer.Project.Entities){
                string properties = String.Join(", ", entity.Properties.Where(p => !p.IsPersistenceIdentity).Select(p => "\"" + p.Name + "\""));
            %]
            if (db.objectStoreNames.contains("[%=entity.Name%]")) {
                db.deleteObjectStore("[%=entity.Name%]"); 
            }
    
            var store = db.createObjectStore("[%=entity.Name%]",
              { keyPath: "id", autoIncrement: true });
    
            store.createIndex([%=properties %], { unique: false });[%}%]
        };
    
        request.onsuccess = function (e) {
            context.indexedDB.db = e.target.result;
        };
    
        request.onerror = context.indexedDB.onerror;
    };
        [%foreach(Entity entity in Producer.Project.Entities){
            string parameters = String.Join(", ", entity.Properties.Where(p => !p.IsPersistenceIdentity).Select(p => p.Name));%]
    context.indexedDB.[%=entity.Name%] = {}
    
        context.indexedDB.[%=entity.Name%].add = function ([%= parameters %]) {
        var db = context.indexedDB.db;
        var trans = db.transaction(["[%=entity.Name%]"], "readwrite");
        var store = trans.objectStore("[%=entity.Name%]");
        var request = store.put({
        [% 
            foreach (Property property in entity.Properties.Where(p => !p.IsPersistenceIdentity)) {%]
            "[%=property.Name%]": [%=property.Name%], [%}%]
            "timeStamp": new Date().getTime()
        });
    
        request.onsuccess = function (e) {
            console.log(e.value);
        };
    
        request.onerror = function (e) {
            console.log(e.value);
        };
    };
    
    context.indexedDB.[%=entity.Name%].delete = function (id) {
        var db = context.indexedDB.db;
        var trans = db.transaction(["[%=entity.Name%]"], "readwrite");
        var store = trans.objectStore("[%=entity.Name%]");
    
        var request = store.delete(id);
    
        request.onsuccess = function (e) {
            console.log(e);
        };
    
        request.onerror = function (e) {
            console.log(e);
        };
    };
    
    context.indexedDB.[%=entity.Name%].loadAll = function () {
        var db = context.indexedDB.db;
        var trans = db.transaction(["[%=entity.Name%]"], "readwrite");
        var store = trans.objectStore("[%=entity.Name%]");
    
        var keyRange = IDBKeyRange.lowerBound(0);
        var cursorRequest = store.openCursor(keyRange);
    
        request.onsuccess = function (e) {
            // not implemented
        };
    
        request.onerror = function (e) {
            console.log(e);
        };
    };
    [%}%]
    
    function init() {
        context.indexedDB.open(); // initialize the IndexDB context.
    }
    
    window.addEventListener("DOMContentLoaded", init, false);
    

    然后您需要通过添加模板生产者来配置您的 CodeFluent 实体项目,并将上面的模板定义为源文件。

    如果您考虑以下模型:

    只需构建它以在目标项目(例如 Web 应用程序)中生成 IndexDB 脚本文件,您就可以像这样操作生成的 API:

    context.indexedDB.Contact.add("Peter", "Boby")
    context.indexedDB.Product.add("Tablet")
    context.indexedDB.Product.add("Computer")
    context.indexedDB.Contact.delete(1)
    context.indexedDB.Product.loadAll()
    

    自定义生产者方法

    不过,如果您需要针对 CodeFluent 实体本身不支持的技术或平台,您可以通过实现 IProducer 接口来创建自己的自定义生产者:

    public interface IProducer
    {
        event Producer.OnProductionEventHandler Production;
    
        void Initialize(Project project, Producer producer);
        void Produce();
        void Terminate();
    }
    

    首先,您需要了解 CodeFluent Entitie Build 引擎会一一调用您配置的每个生产者来生成您的代码。

    首先,CodeFluent Entities 为每个生产者调用Initialize 方法。它将 CodeFluent Entities 项目的实例和当前生产者作为参数。 然后它按照相同的过程调用Product 方法。这是实现您的生成逻辑的正确位置。 最后,您可以在Terminate 方法中实现终结逻辑。

    CodeFluent 提供了一些实现 IProducer 接口的基类,例如 BaseProducer,它位于 CodeFluent.Producers.CodeDom 程序集中,提供“添加缺失的引用”或“更新 Visual Studio 项目 (.XXproj) 等行为。

    此外,这里有一个blog post,可以帮助您将自定义生产者集成到建模器中。

    子生产者方法

    另一种方法可能是开发custom Sub-Producer,但我认为它不适合您的需求。

    【讨论】: