SOLVED look below code snippet.
I have a problem with updating tables, The code shows no faults but it don't act as expected, it does not put any information in the Log Table.
some explenation, i have a table called User with a FK on LogID and a table called Log with PK on LogID so that should be correct, the Log has a column called TimesLoggedIn and one called LastLogedin. and i want to update them accordingly.
User logid = db.Users.Single(p => p.UserID == loginID);
logid.Log.LastLogedin= DateTime.UtcNow;
if (logid.Log.TimesLoggedIn == null)
{
logid.Log.TimesLoggedIn = 1;
}
else
{
logid.Log.TimesLoggedIn = logid.Log.TimesLoggedIn + 1;
}
db.SubmitChanges();
had an embarrassing fault in my code, i had
Response.Redirect("ControlPanel");
placed before i ran the LINQ not after.
I'm using Entity Framework, so I might be wrong. But maybe the Log isn't loaded at all.
Try this:
var options = New DataLoadOptions();
options.LoadWith<Users>(x => x.Log);
db.LoadOptions = options;
// then your code:
User logid = db.Users.Single(p => p.UserID == loginID);
logid.Log.LastLogedin= DateTime.UtcNow;
....
Related
A simple testing setup: department: employee, 1:M and a search form that allows filtering on Emploee FirstName =, lastname =, email contains, age >=, join date <= and related department =.
A search form with widgets bound to parameters of a cloud SQL datasource query script.
A Submit button on the search form which opens up a query results page with a table bound to the cloud SQL query script datasource.
query script
var params = query.parameters;
return getEmployeeRecords_(
params.param_FirstName,
params.param_LastName,
params.param_Email,
params.param_StartDate,
params.param_Age,
params.param_Department
);
and
function getEmployeeRecords_( firstName, lastName, email, startDate, age,
department) {
var ds = app.models.Employee.newQuery();
if ( firstName !== null ) {
ds.filters.FirstName._equals = firstName;
}
if ( lastName !== null ) {
ds.filters.LastName._equals = lastName;
}
if ( email !== null) {
ds.filters.Email._contains = email;
}
if ( startDate !== null) {
ds.filters.StartDate._greaterThanOrEquals = startDate;
}
if ( age !== null) {
ds.filters.Age._lessThanOrEquals = parseInt(age, 10);
}
if ( department !== null) {
ds.filters.Department.Department._equals = department;
}
var records = ds.run();
// intention is to store this value for future use
var recs = records.length;
return records;
}
On the results page for the query script datasource paging is just broken. A query that correctly returns 8 records where the query page size is set to 5 allows me to get the pager to go to page 1000 if I wished, but the datasource always stays on the first page of records. With page size set to e.g., 100 the correct result set is clearly displayed.
In fact everything I do with this sort of query has paging issues. If I insert this code
var ds = app.models.Employee.newQuery();
//ds.filters.FirstName._equals = firstName;
//ds.filters.LastName._equals = lastName;
//ds.filters.Email._contains = '.com';
//ds.filters.StartDate._greaterThanOrEquals = startDate;
ds.filters.Age._lessThanOrEquals = 40;
//ds.filters.Department.Department._equals = department;
ds.sorting.Age._ascending();
var records = ds.run();
return records;
directly into the datasource query script I still have similar paging issues.
If I use a query builder script such as
(
FirstName =? :param_FirstName and
LastName =? :param_LastName and
Email contains? :param_Email and
StartDate >=? :param_Startdate and
Age <=? :param_Age and
Department.Department =? :param_Department
)
and bindings such as
#datasources.Search_Query_Builder.query.parameters.param_FirstName
this works without issue. The same with direct filtering, where we use bindings such as
#datasources.Employee.query.filters.FirstName._equals
Anyone any ideas in terms of what is wrong with this stuff. We need query scripts for more controle, e.g., the ability to retrieve a count of records and where you have to filter for a condition where you restrict data, e.g. a logged in user is related to a client which in turn is related to a property and the property value is restricted according to client.
... Just looking at a real application under development and the use of a query script within the datasource query script editor, no parameters, no binding, just this code:-
var ds = app.models.Incident.newQuery();
ds.filters.Id._greaterThanOrEquals = 200;
ds.filters.Id._lessThanOrEquals = 300;
var records = ds.run();
return records;
and a page size set to 20 and again the paging is up the creek, never moves beyond the first page of records despite the page number incrementing.
I have some suggestions how to address this issue, although it is still unclear what exactly is causing the paging issue and whether or not my suggestions will fix the underlying issue. However, in my own application environment I have several instances where I use a standard SQL model and I apply filters to a datasource from that model and then have a concurrent calculated model (datasource) that returns the total count of records that meet the filters applied to my other datasource. Here we go:
Create a new datasource under your Employee model, leave it on the default 'Query Builder' type, adjust the query page size to your preference, but preferably to something that you know will return more than one page of records when querying the datasource. Uncheck the 'automatically load data' property unless you want to load all records when first going to your page where you set your filters. Do not enter anything in the query builder.
For the calculated datasource that you called Employee_RecordCount add your parameters, FirstName_equals, LastName_equals, Email_contains, StartDate_greaterequals, Age_lessequals, and Departments_equals, if you have not already. In this calculated model you should have a field called RecordCount. In the query script section of this datasource you should put your function as return getEmployeeRecords_(query).
In your server script section where your getEmployeeRecords function is the code should be as follows:
function getEmployeeRecords_(query) {
var params = query.parameters;
var ds = app.models.Employee.newQuery();
if (params.FirstName_equals !== null ) {
ds.filters.FirstName._equals = params.FirstName_equals;
}
if (params.LastName_equals !== null ) {
ds.filters.LastName._equals = params.LastName_equals;
}
if (params.Email_contains !== null) {
ds.filters.Email._contains = params.Email_contains;
}
if (params.StartDate_greaterequals !== null) {
ds.filters.StartDate._greaterThanOrEquals = params.StartDate_greaterequals;
}
if (params.Age_lessequals !== null) {
ds.filters.Age._lessThanOrEquals = parseInt(params.Age_lessequals, 10);
}
if (params.Department_equals !== null) {
ds.filters.Department.Department._equals = params.Department_equals;
}
var records = ds.run();
// update calculated model with record count
var calculatedModelRecord = app.models.Employee_RecordCount.newRecord();
calculatedModelRecord.RecordCount = records.length;
return [calculatedModelRecord];
}
Now go to your search page, create a new panel or form set it to the same new datasource that you created. Make sure you have all your appropriate fields and change the binding of these fields to:
#datasource.query.filters.firstName._equals
#datasource.query.filters.lastName._equals
#datasource.query.filters.email._contains
#datasource.query.filters.StartDate._greaterThanOrEquals
#datasource.query.filters.Age._lessThanOrEquals
#datasource.query.fitlers.Department.Department._equals
The button that initiates your search should have the following code:
var ds = widget.datasource;
ds.load(function() {
app.showPage(app.pages.YourSearchResultPage);
}
var calculatedDs = app.datasources.Employee_RecordCount;
var props = calculatedDs.properties;
props.FirstName_equals = ds.query.filters.firstName._equals;
props.LastName_equals = ds.query.filters.lastName._equals;
props.Email_contains = ds.query.filters.email._contains;
props.StartDate_greaterequals = ds.query.filters.StartDate._greaterThanOrEquals;
props.Age_lessequals = ds.query.filters.Age._lessThanOrEquals;
props.Department_equals = ds.query.filters.Department.Department._equals;
calculatedDs.load();
Now go to your search result page and make sure the you have the following elements:
A panel that the datasource is set to Employee_RecordCount. Inside
this panel create a label and set the binding to
#datasource.item.RecordCount.
A table that has the datasource set
to the same datasource as created in the first step. Make sure your
table has 'pagination' turned on.
That should be all, and this works in my application. It is a pain to set up, but I'm afraid it is the only workaround to have a total count of records. I should note that I have never had any paging issues either.
I'm sure I'm doing something wrong... but every time I query on a calculated datasource, I get the error "cannot handle returning cyclic object."
Here's the gist:
I have a calculated model that fetches a user's google contacts and places the full name field into a table on the UI. The goal is to have a separate text box that can be used to search the full name field and then repopulate the table on the same page with the results of the search, similar to how google contacts search behavior works. The on value change event of the text box sends the textbox value to this server script:
function searchContacts (sq) {
var ds = app.models.Contacts.newQuery();
ds.filters.FullName._contains = sq;
var results = ds.run();
return results;
}
But every time I get the cyclic object error when the values are returned from that function. The error actually fires when the query run command (ds.run) is executed.
I've tried querying the datasource as well, but I've read somewhere that you can't query the datasource of a calculated model because it doesn't exist, so you have to query the model.
Any help would be much appreciated.
From your question it is not 100% clear, what you are trying to do. In case you are actually using Calculated Model, then your Server Script Query should look like this:
var sq = query.parameters.SearchQuery;
var contactsQuery = app.models.Contacts.newQuery();
contactsQuery.filters.FullName._contains = sq;
var contacts = ds.run();
var results = contacts.map(function(contact) {
var calcRecord = app.MyCalcModel.newRecord();
calcRecord.Name = contact.FullName;
return calcRecord;
});
return results;
Note, that you cannot return objects of arbitrary type from Server Script Query, only of type of this particular Calculated Model.
But from some parts of your description and error text if feels like you are trying to load records with async serever call using google.scritp.run. In this case you cannot return App Maker records(App Script doesn't allow this) and you need to map them to simple JSON objects.
I don't think I was super-clear on my original post.
I have a calculated model that is all of the user's contacts from Google Contacts (full name, email, mobile, etc...) On the UI I have a list widget that's populated with all of the Full Name fields and above the list widget a text input that's used to search the list widget. So the search text box's on input change event sends a request to query the Full Names, similar to how Google Contact's search feature works.
Screen Shot
It appears that App Maker doesn't let you query calculated models, so I have this workaround - unless someone comes up with something better:
This is the onInputChange handler for the search text box:
sq = app.pages.SelectClient.descendants.TextBox1.value;
app.datasources.SearchContacts.query.parameters.Name = sq;
app.datasources.SearchContacts.load();
This is the Server Script Code (thanks to #Pavel Shkleinik for the heads up):
var sq = query.parameters.Name;
if (sq !== null) {
return getContactsbyName(sq);
} else {
return getContacts();
}
And the server code with no query:
function getContacts() {
var results = [];
var contacts = ContactsApp.getContacts();
contacts.forEach(function(item) {
var contact = app.models.Contacts.newRecord();
contact.FullName = item.getFullName();
var emails = item.getEmails(ContactsApp.Field.WORK_EMAIL);
if (emails.length > 0) {
contact.PrimaryEmail = emails[0].getAddress();
}
contact.LastName = item.getFamilyName();
contact.FirstName = item.getGivenName();
var phones = item.getPhones(ContactsApp.Field.MOBILE_PHONE);
if (phones.length > 0) {
contact.Mobile = phones[0].getPhoneNumber();
}
var addresses = item.getAddresses(ContactsApp.Field.WORK_ADDRESS);
if (addresses.length > 0) {
contact.Address = addresses[0].getAddress();
}
results.push(contact);
results.sort();
});
return results;
}
And with the query:
function getContactsbyName(sq) {
var results = [];
var contacts = ContactsApp.getContactsByName(sq);
contacts.forEach(function(item) {
var contact = app.models.Contacts.newRecord();
contact.FullName = item.getFullName();
var emails = item.getEmails(ContactsApp.Field.WORK_EMAIL);
if (emails.length > 0) {
contact.PrimaryEmail = emails[0].getAddress();
}
contact.LastName = item.getFamilyName();
contact.FirstName = item.getGivenName();
var phones = item.getPhones(ContactsApp.Field.MOBILE_PHONE);
if (phones.length > 0) {
contact.Mobile = phones[0].getPhoneNumber();
}
var addresses = item.getAddresses(ContactsApp.Field.WORK_ADDRESS);
if (addresses.length > 0) {
contact.Address = addresses[0].getAddress();
}
results.push(contact);
results.sort();
});
return results;
}
This way, the list populates with all of the names when there's no search query present, and then re-populates with the search query results as needed.
The only issue is that the call to the Google Contacts App to populate the Calculated Model is sometimes very slow.
I am developing a mobile application with Ionic and SQLITE database. I want a scenario where same record should not be inserted twice for Inventory operation. I am checking the database as follows:
var query = "SELECT COUNT(*) FROM productScan WHERE uniqueId = (?) AND sync = \'N\'";
$cordovaSQLite.execute(db, query, [uniqueId]).then(function (res) {
alert(JSON.stringify(res));
}, function (err) {
alert(JSON.stringify(err));
});
what happen here is when i install the app for the first time and run it then after scan operation when this code run for duplication check, it gives me following output even though there is no record in database
{"rows":{"length":1},""rowsAffected":0}
I am new to Structured Query Language(SQL). I am not able to parse the result here. The result is coming wrong. Is the query needs to be reformatted or any different way to achieve the goal?
Thanks for your time.
BEST way to do this is by giving ALIAS to the COUNT(*) .
something like this
db.executeSql("select count(*) AS TOTAL from mydebit where aid = ?", [
parseInt(this.mydata)
]);
and then
console.log(data.rows.item(0).TOTAL)
so we can easily give the name to the return result and use the to get he row value
cheersss.....!!!!!!!!!
I do it in this way
JSON.stringify(data.rows.item(0)['COUNT(*)'])
Somehow i managed to achieve it in a different way
var query = "SELECT * FROM productScan WHERE uniqueId = (?) AND sync = \'N\'";
$cordovaSQLite.execute(db, query, [uniqueId]).then(function (res) {
if (res.rows.length == 0) {
//processed the operation
}else{
alert('You have already scanned this asset!.');
}
var query = "SELECT COUNT(*) FROM productScan WHERE uniqueId = (?) AND sync = \'N\'";
$cordovaSQLite.execute(db, query, [uniqueId]).then(function (res) {
just parse the result,(json.parse(res)) and find by rowsAffected like
if(rowsAffected != 0)
{
//just do the operation
}
else {
//terminate
}
I can't explain the code. Look at different behavior:
var project = DB.Project.Find(1000111);
project.MustLinkToMF = false;
// Includes id = 1000111; MustLinkToMF = false; - From Cache?
var projects1 = DB.Project.Select(p => p).ToList();
// Doesn't contain 1000111! - Not From Cache?
var projects2 = DB.Project.Where(p => p.MustLinkToMF == false).Select(p => p).ToList();
DB.SaveChanges();
How to get cached data, included my changes?
How Can I get projects2 using one simple query before SaveChanges?
Thank you!
You can navigate through entities in the first level cache:
ctx.ChangeTracker.Entries().Where(x => x.State == EntityState.Modified).Select(x => x.Entity).OfType<T>()
Just replace EntityState.Modified for what you want.
See an example here: https://weblogs.asp.net/ricardoperes/entity-framework-code-first-get-entities-from-local-cache-or-the-database
I have two sample tables:
SCENARIO 1
TABLE 1 - INGREDIENT
ingredientId(PK, int, not null)
userId(FK, int, not null)
timestamp(datetime, not null)
TABLE 2 - INGREDIENT ADDITIONAL INFORMATION
ingredientAdditionalInformationId(PK, int, not null)
ingredientId(FK, int, not null)
isApproved(bit, not null)
unitsConverted(bit, not null)
SELECT SENTENCE IN CODE BEHIND:
public IQueriable GetIngredientData(int ingredientId)
{
using (var context = new MyEntities())
{
var result = context.Ingredient
.Where(i => i.ingredientId == ingredientId)
.Select(i => new
{
i.ingredientId,
i.userId
i.IngredientAdditionalInformation.FirstOrDefault(iai => iai.ingredientId = i.ingredientId).isApproved
i.IngredientAdditionalInformation.FirstOrDefault(iai => iai.ingredientId = i.ingredientId).unitsConverted
});
return result.ToList().AsQueriable();
}
}
or select with join (I know that you can join with method syntax but I can write join with query method faster)
public IQueriable GetIngredientData(int ingredientId)
{
using (var context = new MyEntities())
{
var result = from i in context.Ingredient
join iai in context.IngredientAdditionalInformation on i.ingredientId equals iai.ingredientId
where i.ingredientId == 1
select new
{
i.ingredientId,
i.userId
iai.isApproved
iai.unitsConverted
};
return result.ToList().AsQueriable();
}
}
Which one is better/faster with join or FirstOrDefault() or I should write database table different like in example 2 below:
SCENARIO 2
TABLE 1 - INGREDIENT
ingredientId(PK, int, not null)
userId(FK, int, not null)
timestamp(datetime, not null)
TABLE 2 - INGREDIENT
ingredientId(PK, FK, int, not null) //WITHOUT PRIMARY (ingredientAdditionalInformationId) AUTO INCREMENT KEY)
isApproved(bit, not null)
unitsConverted(bit, not null)
Because I know that every ingredient have only one additional info...
SELECT SENTENCE IN CODE
using (var context = new MyEntities())
{
var result = context.Ingredient
.Where(i => i.ingredientId = 1)
.Select(i => new
{
i.ingredientId,
i.userId
i.IngredientAdditionalInformation.isApproved
i.IngredientAdditionalInformation.unitsConverted
});
}
I would like to know which table design is better (SCENARIO1 or SCENARIO2) for optimized select, if I really need auto increment key in ingredientAdditionalInformation if I know that there will be only one entry for every Ingredient and if this is the right way to use entity framework?
If you're maintaining a one-to-one relationship between the two tables, then your second design is better, because it will also ensure referential integrity in your database.
You can then make the property a single navigation property in your entity framework model, and simplify your EF query as follows. If you have lazy loading of navigational properties enabled in your model, you may be able to get away without using the include if you're
var result = from i in context.Ingredient.Include("IngredientAdditionalInformation") select i;
And then access the properties as follows:
i.IngredientAdditionalInformation.isApproved
However, do you really need an additional table? With only three properties on each I'd just combine them into one table and then you have all the properties available to you immediately.
Scenario 2 is better since you are saying there is a one-to-one relationship between the two tables.
Another option you should explore is using Table Per Type Inheritance. You will not need to specify eager loading using Include nor joins in this case.
Assuming your table1 = IngredientBase and table2 = Ingredients and in your context you have set up
public IQueryable<Ingredient> Ingredients {
get { return IngredientBases.OfType<Ingredient>(); } }
then you'll just need
using (var context = new MyEntities())
{
var result = context.Ingredients.Where(i => i.ingredientId = 1);
}
SQL wise, the 2nd select of scenario1 and scenario2 will produce nearly equivalent plans. But performance wise, scenario2 will be better, not to mention being the right design for a 1-1 relationship tables.