Note: This code used to work as I used PostgreSQL. After switching to MySQL these functions stopped working for some reason.
I double checked: languageId and shopId are valid IDs and there is a valid entry of supported_language resembling the inserted record after fetchOne() but it returns null.
private Long addSupportedLanguage(Long languageId, Long shopId) {
Long value = this.ctx.insertInto(SHOP_LANGUAGE)
.set(SHOP_LANGUAGE.LANGUAGE_ID, languageId)
.set(SHOP_LANGUAGE.SHOP_ID, shopId)
.returning()
.fetchOne() // After this line I see the record in my db but it returns null
.getValue(SHOP_LANGUAGE.LANGUAGE_ID);
return value;
}
I also tried using
.returning(RESTAURANT_LANGUAGE.LANGUAGE_ID)
but the result is the same.
I am observing something similar when calling returnin() after a delete() statement:
public void deleteEmailVerificationToken(String token) {
ShopAdminVerificationTokenRecord shopAdminVerificationTokenRecord = this
.ctx.delete(SHOP_ADMIN_VERIFICATION_TOKEN)
.where(SHOP_ADMIN_VERIFICATION_TOKEN.VERIFICATION_TOKEN.eq(token))
.returning()
.fetchOne()
.into(SHOP_ADMIN_VERIFICATION_TOKEN);
if(shopAdminVerificationTokenRecord != null) {
LOGGER.debug("Deleted verification token for " + shopAdminVerificationTokenRecord.getUserEmail());
} else {
LOGGER.debug("The given token was not found.");
}
}
I don't understand why this is happening. The new record gets correctly inserted but still I cannot fetch that record immediately after insertion.
I created SHOP_LANGUAGE and all other objects using the jOOQ code generator. This is the SQL CREATE TABLE statement that I used to create the table for a MySQL database:
CREATE TABLE shop_language (
shop_id BIGINT NOT NULL,
CONSTRAINT fk__shop_language__shop
FOREIGN KEY (shop_id)
REFERENCES shop(id),
language_id BIGINT NOT NULL,
CONSTRAINT fk__shop_language__language
FOREIGN KEY (language_id)
REFERENCES language(id),
PRIMARY KEY (shop_id, language_id)
);
As mentioned in the comments:
DELETE .. RETURNING is not supported for MySQL as documented by the #Support annotation on the relevant returning() methods.
Related
I have tried reading the docs, but I don't get why the Update method produces a "Duplicate entry" MySQL error.
The docs says
In its most simple form, updating any model without any filters will update every field, except the Id which is used to filter the update to this specific record:
So I try it, and pass in an object, like below. A row with id 2 already exists.
using (var _db = _dbFactory.Open())
{
Customer coreObject = new Customer(...);
coreObject.Id = 2;
coreObject.ObjectName = "a changed value";
_db.Update<Customer>(coreObject); // <-- error "duplicate entry"
}
Yes, there are options using .Save and such, but what am I missing with the .Update? As I read it, it should use its Id property to update the row in the db, not insert a new row?
The issue with this method is that you're updating a generic object T but your Update API says to update the Concrete Customer type:
public void MyTestMethod<T>(T coreObject) where T : CoreObject
{
long id = 0;
using (var _db = _dbFactory.Open())
{
id = _db.Insert<T>(coreObject, selectIdentity: true);
if (DateTime.Now.Ticks == 0)
{
coreObject.Id = (uint)id;
_db.Delete(coreObject);
}
if (DateTime.Now.Ticks == 0)
{
_db.DeleteById<Customer>(id);
}
if (DateTime.Now.Ticks == 0)
{
coreObject.Id = (uint)id;
coreObject.ObjectName = "a changed value";
_db.Update<Customer>(coreObject);
}
}
}
Which OrmLite assumes that you're using a different/anonymous object to update the customer table, similar to:
db.Update<Customer>(new { Id = id, ObjectName = "a changed value", ... });
Which as it doesn't have a WHERE filter will attempt to update all rows with the same primary key.
What you instead want is to update the same entity, either passing in the Generic Type T or have it inferred by not passing in any type, e.g:
_db.Update<T>(coreObject);
_db.Update(coreObject);
Which will use OrmLite's behavior of updating entity by updating each field except for Primary Keys which it instead used in the WHERE expression to limit the update to only update that entity.
New Behavior in v5.1.1
To prevent accidental misuse like this I've added an Update API overload in this commit which will use the Primary Key as a filter when using an anonymous object to update an entity, so your previous usage:
_db.Update<Customer>(coreObject);
Will add the Primary Key to the WHERE filter instead of including it in the SET list. This change is available from v5.1.1 that's now available on MyGet.
given below is the method I used to retrieve details from a Dynamodb table. But when I call this method it ended up throwing an exception "Unable to locate property for key attribute appointmentId". primary key of this particular table is appointmentId, but I've already created a global secondary index on patientId column. I'm using that index in below query to get the appointment details by a given patientID.
public async Task GetAppointmentByPatientID(int patientID)
{
var context = CommonUtils.Instance.DynamoDBContext;
PatientAppointmentObjectList.Clear();
DynamoDBOperationConfig config = new DynamoDBOperationConfig();
config.IndexName = DBConstants.APPOINTMENT_PATIENTID_GSI;
AsyncSearch<ScheduledAppointment> appQuery = context.QueryAsync<ScheduledAppointment>(patientID.ToString(), config);
IEnumerable<ScheduledAppointment> appList = await appQuery.GetRemainingAsync();
appList.Distinct().ToList().ForEach(i => PatientAppointmentObjectList.Add(i));
if (PropertyChanged != null)
this.OnPropertyChanged("PatientAppointmentObjectList");
}
}
It was a silly mistake. I've had the hash key column of the table as "appointmentID" and the model object property named as AppointmentID. mismatch in the case of the property name had confused the dynamodb mapping.
I'm doin a simple query linq to retrieve a label from an optionSet. Looks like the formatted value for the option set is missing. Someone knows why is not getting generated?
Best Regards
Sorry for the unclear post. I discovered the problem, and the reason of the missing key as formattedvalue.
The issue is with the way you retrieve the property. With this query:
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.PaymentTermsCode
}
I was retrieving the correct int value for the option set, but what i needed was only the text. I changed the query this way:
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.FormattedValues["paymenttermscode"]
}
In this case I had an error stating that the key was not present. After many attempts, i tried to pass both the key value and the option set text, and that attempt worked just fine.
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.PaymentTermsCode,
paymenttermscodeValue = d.FormattedValues["paymenttermscode"]
}
My guess is that to retrieve the correct text associated to that option set, in that specific entity, you need to retrieve the int value too.
I hope this will be helpful.
Best Regards
You're question is rather confusing for a couple reasons. I'm going to assume that what you mean when you say you're trying to "retrieve a label from an OptionSet" is that you're attempting to get the Text Value of a particular OptionSetValue and you're not querying the OptionSetMetadata directly to retrieve the actual LocalizedLabels text value. I'm also assuming "formatted value for the option set is missing" is referring to the FormattedValues collection. If these assumptions are correct, I refer you to this: CRM 2011 - Retrieving FormattedValues from joined entity
The option set metadata has to be queried.
Here is an extension method that I wrote:
public static class OrganizationServiceHelper
{
public static string GetOptionSetLabel(this IOrganizationService service, string optionSetName, int optionSetValue)
{
RetrieveOptionSetRequest retrieve = new RetrieveOptionSetRequest
{
Name = optionSetName
};
try
{
RetrieveOptionSetResponse response = (RetrieveOptionSetResponse)service.Execute(retrieve);
OptionSetMetadata metaData = (OptionSetMetadata)response.OptionSetMetadata;
return metaData.Options
.Where(o => o.Value == optionSetValue)
.Select(o => o.Label.UserLocalizedLabel.Label)
.FirstOrDefault();
}
catch { }
return null;
}
}
RetrieveOptionSetRequest and RetrieveOptionSetResponse are on Microsoft.Xrm.Sdk.Messages.
Call it like this:
string label = service.GetOptionSetLabel("wim_continent", 102730000);
If you are going to be querying the same option set multiple times, I recommend that you write a method that returns the OptionSetMetadata instead of the label; then query the OptionSetMetadata locally. Calling the above extension method multiple times will result in the same query being executed over and over.
This question already has answers here:
How to get the identity of an inserted row?
(15 answers)
Closed 8 years ago.
public int retrieveID()
{
int lastEntry = 0;
try
{
queryString = "Select ID from Database";
myComm = new OleDbCommand(queryString, myConn);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return lastEntry;
}
I want to retrieve the last primary key used in access database, whereas i set my primary key as autonumber.
elaborating more..
I am working on a database application and want to utilize the primary key, eg if the last entry in the database was 10, i want to retrieve 10, i tried simple query but that didnot work.
If you are using an OLEDB connection then this should work
queryString = "SELECT ##IDENTITY";
Note that this should be called immediately after the INSERT that creates the record for which you want to save the ID value. If your code were to create other records with Identity (AutoNumber) fields then the ##IDENTITY value will be updated (replaced) by those calls.
I'm getting a strange error while trying to select a row from a table under Windows Azure Table Storage. The exception "An item with the same key has already been added." is being thrown even though I'm not inserting anything. The query that is causing the problem is as follows:
var ids = new HashSet<string>() { id };
var fields = new HashSet<string> {"#all"};
using (var db = new AzureDbFetcher())
{
var result = db.GetPeople(ids, fields, null);
}
public Dictionary<string, Person> GetPeople(HashSet<String> ids, HashSet<String> fields, CollectionOptions options)
{
var result = new Dictionary<string, Person>();
foreach (var id in ids)
{
var p = db.persons.Where(x => x.RowKey == id).SingleOrDefault();
if (p == null)
{
continue;
}
// do something with result
}
}
As you can see, there's only 1 id and the error is thrown right at the top of the loop and nothing is being modified.
However, I'm using "" as the Partition Key for this particular row. What gives?
You probably added an object with the same row key (and no partition key) to your DataServiceContext before performing this query. Then you're retrieving the conflicting object from the data store, and it can't be added to the context because of the collision.
The context tracks all object retrieved from the Tables. Since entities are uniquely identified by their partitionKey/rowKey combination, a context, like the tables, cannot contain duplicate partitionkey/rowkey combinations.
Possible causes of such a collison are:
Retrieving an entity, modifying it, and then retrieving it again using the same context.
Adding an entity to the context, and then retrieving one with the same keys.
In both cases, the context the encounters it's already tracking a different object which does however have the same keys. This is not something the context can sort out by itself, hence the exception.
Hope this helps. If you could give a little more information, that would be helpful.