0

I have created a sample database and test scripts with it. The database structure is:

enter image description here

I have created a JSFiddle for it: fiddle Click all the buttons except stress test on the top, then click the tests.

The problem is, it perfectly works with provider webSql, but it fails on the provider indexedDb. I downloaded the pro packages and it makes test 3 work partially but it still fails on test 2 completely. The problem i found is when i query the database with join relation(ex: employees in with department.ID is 1) indexedDb cannot process this request.

How can circumvent this situation?

Whole code is:

index.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
  <script src="jaydataPro/jaydata.min.js"></script>
  <script src="jaydataPro/jaydataproviders/IndexedDbProProvider.min.js"></script>
  <script src="jaydataPro/jaydataproviders/SqLiteProProvider.min.js"></script>
  <script src="jaydataPro/jaydataproviders/WebApiProvider.min.js"></script>
  <script src="jaydataPro/jaydataproviders/YQLProvider.min.js"></script>
  <script src="sampledatabase.js"></script>
  <script src="test.js"></script>
  <title>Jaydata Test</title>
</head>

<body>
  <div>
    <h3>Database Generation</h3>
    <div>
      <button onclick="TestAddDepartments(5);">Add Departments</button>
    </div>
    <div>
      <button onclick="AddEmployeeList(TestEmployeeList(1,100),1);"> Employees 1</button>
      <button onclick="AddEmployeeList(TestEmployeeList(101,100),2);">Employees 2</button>
      <button onclick="AddEmployeeList(TestEmployeeList(201,100),3);">Employees 3</button>
      <button onclick="AddEmployeeList(TestEmployeeList(301,100),4);">Employees 4</button>
      <button onclick="AddEmployeeList(TestEmployeeList(401,100),5);">Employees 5</button>
    </div>
    <div>
      <button onclick="AddStockList(TestStockList(1,400),1);">
      Stocks 1</button>
      <button onclick="AddStockList(TestStockList(401,400),2);">
      Stocks 2</button>
      <button onclick="AddStockList(TestStockList(801,400),3);">
      Stocks 3</button>
      <button onclick="AddStockList(TestStockList(1201,400),4);">
      Stocks 4</button>
      <button onclick="AddStockList(TestStockList(1601,400),5);">
      Stocks 5</button>
    </div>
    <div>
      <button onclick="AddStockList(TestStockList(2001,5000),2);">
      Stress Test for Test 3</button>
    </div>
  </div>
  <div>
    <h3>Queries</h3>
      <button onclick="TestSearchEmployeeName1()">Test 1</button>
      <button onclick="TestSearchEmployeeName2()">Test 2</button>
      <button onclick="TestSearchEmployeeName3()">Test 3</button>
  </div>
  <div>
    <h3>Results</h3>
    <p id='Result'>Result</p>
  </div>
</body>
</html>

sampledatabase.js:

/*
  x is a database
  Database name is Company
  Company has 3 tables:
    =Departments
      -ID(key,computed)
      -DepartmentName(string,required)
    =Employees
      -ID(key,computed)
      -Name(string,required)
    =Stocks
      -ID(key,computed)
      -Description(string)
      -NumItems(int,required)
  Employee is connected to Department
  Stock is connected to Department
  Department has a list of Stocks and Employees
To do:
  -insert websql and indexeddb translations to the document
*/



$data.Entity.extend("Org.Employee",{
  ID: {key: true, type: "integer", computed: true},
  Name: {type: "string", required: true},
  Department: {type: "Org.Department", inverseProperty: "Employees"}
});

$data.Entity.extend("Org.Stock",{
  ID: {key: true, type: "integer", computed: true},
  Description: {type: "string"},
  NumItems: {type: "integer", required: true},
  Department: {type: "Org.Department", inverseProperty: "Stocks"}
});

$data.Entity.extend("Org.Department",{
  ID: {key: true, type: "integer", computed: true},
  DepartmentName: {type: "string", required: true},
  Employees:{type: Array, elementType: "Org.Employee", inverseProperty:"Department"},
  Stocks:{type: Array, elementType: "Org.Stock", inverseProperty:"Department"}
});

$data.EntityContext.extend("Company",{
  Employees: {type: $data.EntitySet, elementType: Org.Employee},
  Departments: {type: $data.EntitySet, elementType: Org.Department},
  Stocks: {type: $data.EntitySet, elementType: Org.Stock}
});

var x= new Company({
  provider: "indexedDb",
  databaseName: "DB",
  version: 1,
  dbCreation: $data.storageProviders.DbCreationType.DropAllExistingTables
});

function AddEmployee(emp,department)
{
  x.Departments.first(
    function(it){
      return it.ID==department.valueOf()
    }, 
    {emp:emp,department:department}, 
    function(dep){
      x.Departments.attach(dep);
      emp.Department=dep;
      x.Employees.add(emp);
      x.Employees.saveChanges();
    }
  );
}

function RemoveEmployee(emp_id)
{
  x.Employees.first(
    function(res){
      return res.ID==emp_id.valueOf();
    },
    {emp_id:emp_id},
    function(emp)
    {
      x.Employees.remove(emp);
      x.Employees.saveChanges();
    }
  );  
}

function ChangeEmployeeName(emp_id,new_name)
{
  x.Employees.first(
    function(res){
      return res.ID==emp_id.valueOf();
    },
    {emp_id:emp_id,new_name:new_name},
    function(emp)
    {
      x.Employees.attach(emp);
      emp.Name=new_name;
      x.Employees.saveChanges();
    }
  );
}

function RemoveDepartment(dep_id)
{
  x.Employees.filter(
    function(res){
      return res.Department.ID==dep_id
    },
    {dep_id:dep_id}
  ).forEach(
    function(it){
      x.Employees.remove(it)
    });
  x.Employees.saveChanges();
  x.Departments.first(
    function(it)
    {
      return it.ID==dep_id;
    },
    {dep_id:dep_id},
    function(dep)
    {
      x.Departments.remove(dep);
      x.Departments.saveChanges();
    }
  );
}

function AddStock(stock,department)
{
  x.Departments.first(
    function(it){
      return it.ID==department.valueOf()}, 
      {emp:emp,department:department}, 
      function(dep){
        x.Departments.attach(dep);
        stock.Department=dep;
        x.Stocks.add(stock);
        x.Stocks.saveChanges();
      });
}

function AddEmployeeList(list,department)
{
  x.Departments.first(
    function(it){return it.ID==department.valueOf()}, 
    {department:department,list:list}, 
    function(dep){
      for (var i = 0; i < list.length; i++) {
        list[i].Department=dep;
      };
      x.Departments.attach(dep);
      x.Employees.addMany(list);
      x.Employees.saveChanges();
    });
}

function AddStockList(list,department)
{
  x.Departments.first(
    function(it){return it.ID==department.valueOf()}, 
    {department:department,list:list}, 
    function(dep){
      for (var i = 0; i < list.length; i++) {
        list[i].Department=dep;
      };
      x.Departments.attach(dep);
      x.Stocks.addMany(list);
      x.Stocks.saveChanges();
    });
}

test.js:

//testing script

function TestAddDepartments(number)   //number of departments
{
  var dep='Department';
  for (var i = 1; i <= number.valueOf(); i++)
  {
    var temp=dep+i.toString();
    x.Departments.add({DepartmentName:temp});
  };
  x.Departments.saveChanges();
}

function TestEmployeeList(start,number)
{
  emp_list=new Array();
  var emp='Employee';
  for (var i = start.valueOf(); i < start.valueOf()+number.valueOf(); i++)
  {
    var temp=emp+i.toString();
    emp_list.push({Name:temp});
  };
  return emp_list;
}

function TestStockList(start,number)
{
  stock_list=new Array();
  var stock='Stock';
  for (var i = start.valueOf(); i < start.valueOf()+number.valueOf(); i++)
  {
    var temp=stock+i.toString();
    var num=Math.floor((Math.random()*1000)+1);
    stock_list.push({Description:temp,NumItems:num});
  };
  return stock_list;
}

/*function TestSearchEmployeeName(number,limit)
{
  var start= new Date().getTime();
  var emp='Employee';
  for (var i = 1; i <= number.valueOf(); i++)
  {
    num=Math.floor((Math.random()*limit.valueOf())+1);
    search=emp+num.toString();
    x.Employees.filter(
      function(res)
      {
        return res.Name==search;
      }).
    forEach(
      function(it)
      {
        console.log(it.Name);
      });
  };
  var elapsed=new Date().getTime()-start;
  console.log("Searching the database with "+number.toString()+
    " entries took "+elapsed.toString()+" milliseconds");
}
*/

//Static tests
function TestSearchEmployeeName1()
{
  var start= new Date().getTime();
  x.Employees.filter(
    function(res)
    {
      return res.Name=='Employee43';
    },{start:start}).
  toArray(function(it){
    var elapsed=new Date().getTime()-start;
    var res="Query with "+it.length.toString()+" result took "+
      elapsed.toString()+" milliseconds";
    document.getElementById('Result').innerHTML = res;
  },{start:start}
  );
}

function TestSearchEmployeeName2()
{
  var start= new Date().getTime();
  x.Employees.filter(
    function(res)
    {
      return res.Department.ID==1;
    },{start:start}).
  toArray(function(it){
    var elapsed=new Date().getTime()-start;
    var res="Query with "+it.length.toString()+" results took "+
      elapsed.toString()+" milliseconds";
    document.getElementById('Result').innerHTML = res;
  },{start:start}
  );
}

function TestSearchEmployeeName3()
{
  var start= new Date().getTime();
  x.Stocks.filter(
    function(res)
    {
      return res.NumItems>258 || res.Department.ID<3;
    },{start:start}).
  toArray(function(it){
    var elapsed=new Date().getTime()-start;
    var res="Query with "+it.length.toString()+" results took "+
      elapsed.toString()+" milliseconds";
    document.getElementById('Result').innerHTML = res;
  },{start:start}
  );
}
4

1 回答 1

3

According to the provider feature matrix, the include() and complex type mapping features aren't implemented yet for IndexedDB, this means you cannot have navigation properties in IndexedDB, only in SQLite/WebSQL. You can propose this feature at the user voice page.

于 2013-07-01T10:59:06.853 回答