Objectify - How to get auto generated id of the entity, when Long is used? - objectify

How to get auto generated id of the entity, when Long is used? I have an entity like below
#Entity
public class DailyChallenge {
#Id
public Long id;
public String title;
}
Here id will be auto generated. How can I get this id?

The id is set on the entity once you save it to objectify.
DailyChallenge de = new DailyChallenge();
de.title = "some title";
ObjectifyService.ofy().save().entities(de).now();
System.out.println(de.id); // This is non null now.

Related

EF - Conditionally allow saving a property value (which has a backing field)

I have a User entity and an EmailRecipient entity with a -one-to-one relationship. Email recipients can also be created without a related User entity.
My EmailRecipient entity takes the Name, Surname and EmailAddress from the User entity if it is attached/included. I have set up the properties to return the backing-field value if it isn't null before it returns the User properties so I can specify an alternative name if I want.
When saving the EmailRecipient, EF looks at the Name, Surname and EmailAddress properties and populates the EmailRecipient table with the values from the User entity instead of using the backing field values. I would like these fields to remain NULL in the database providing I haven't set a value explicitly i.e. recipient.Name = "new name";
My Question: How can I make EF populate selected database fields based on the backing-field value instead of the property values? Or is there a completely different approach to solving this problem?
EmailRecipient Entity:
public class EmailRecipient
{
private string _name;
public virtual string Name
{
get { return User == null ? _name : _name ?? User.Name; }
set { _name = value; }
}
private string _surname;
public virtual string Surname
{
get { return User == null ? _surname : _surname ?? User.Surname; }
set { _surname = value; }
}
private string _emailAddress;
public virtual string EmailAddress
{
get { return User == null ? _emailAddress : _emailAddress ?? User.EmailAddress; }
set { _emailAddress = value; }
}
[Key, ForeignKey(nameof(UserId))]
public User User { get; protected set; }
public long? UserId { get; set; }
}
After some further digging, I think I have found the solution. Carefully reading Microsoft's EF Core backing fields documentation, it seems that we can explicitly ask EF to read and write to the backing field instead of using the property.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<EmailRecipient>().Property(x => x.Name)
.UsePropertyAccessMode(PropertyAccessMode.Field);
}
The backing field remains null until a new Name is set i.e. recipient.Name = "new name"; and because of this, I can use the recipient.Name property to return the recipient._name (as stored in the database) or if it is null, the recipient.User.Name

asp.net ef code first duplicate elements with foreign key

I have the following code :
public Exam CreateExam(string name, List<Question> questions, DateTime timeNow)
{
User user = GetUserByName(name);
Exam exam = new Exam()
{
Questions = questions,
StartDate = timeNow,
User = user
};
Context.Exams.Add(exam);
Context.SaveChanges();
return exam;
}
Exam :
public class Exam
{
public int Id { get; set; }
public DateTime StartDate { get; set; }
public User User { get; set; }
public virtual List<Question> Questions { get; set; }
}
And user has the basic user infos.
My problem is that when I create an exam for the user, the save change also add a new user to the database, with only the ID being different. How do I prevent that and make it understand that I want to link it to the existing user ?
Thank you !
Edit: GetUserByName() :
Context.Database.SqlQuery<User>("Select * from Users where name = #name", new SqlParameter("name", name)).FirstOrDefault();
When you use SqlQuery to fetch user, he will not be tracked by Entity Framework, because you can write arbitrary query and map result to User class. So EF consider, that he is new one, when you reference to him. To fix this problem, you should manually attach his to context:
User user = GetUserByName(name);
Context.Users.Attach(user);
Based Slava Utesinov answer Entity Framework's change tracker does not track entity changes when get from raw query such as:
Context.Database.SqlQuery<User>("Select * from Users where name = #name", new SqlParameter("name", name)).FirstOrDefault();
Therefore when you call SaveChanges() method, Entity Framework change tracker detect user entity state as Added (new entity)
1.you can use DbSet.SqlQuery instead of Database.SqlQuery because DbSet.SqlQuery will tracked by the context:
Context.Users.SqlQuery("Select * from Users where name = #name", new SqlParameter("name", name)).FirstOrDefault();
or
2.you can attach entity to current context dbset as unchanged state

What's the best way to model Custom Object for Document ID in Firestore?

Say I have a collection of 'Users', and am happy for their ID to be the generated Firestore documentId, something like:
Users Collection
GENERATED_FIRESTORE_ID1:
name: "User 1 name"
...: etc.
GENERATED_FIRESTORE_ID2:
name: "User 2 name"
...: etc."
and I am adding them, and retrieving them with a custom object (I'm using Android at the moment but the question I guess is more generalistic). I don't want to have an extra "id" field in the document, just use the document.getId() method to get the generated firestore ID.
Is there a correct way to map a POJO to not have an indivual ID field, but when querying set it for application usage? I am doing it using the #Exclude annotation as follows:
public class User {
// as a side question, do I need #exclude on the field or just the getter?
#Exclude
String uId;
String name;
String email;
//... additional fields as normal
public User() {
}
#Exclude
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.displayName = name;
}
//... etc. etc.
}
and then I create the User object and set its ID as follows:
for (DocumentSnapshot doc : documentSnapshots) {
User user = doc.toObject(User.class);
user.setId(doc.getId());
users.add(user );
}
This works fine, and apologies if this is indeed the way, but I'm new to FireStore (am loving it) and want to make sure I'm doing it right. I just wondered if there was a way this would all be automatic, without #Exclude and then manually setting the ID after doc.toObject(MyCustomObject.class)
There is now an Annotation for this -
You could simply use
#DocumentId
String uID
https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/DocumentId.html

Spring Data JPA method for deleting using a two fields in the embaddable key

THis is the main entity class, which is having an embeddedId
public class LabResHivMutation implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private LabResHivMutationPK id;
private String comments;
#Column(name="MUTATION_TYPE_ID")
private BigDecimal mutationTypeId;
#Column(name="VALUE")
private String value;
}
This is the embeddable key
#Embeddable
public class LabResHivMutationPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
#Column(name="TO_INST")
private Long toInst;
#Column(name="REL_INVSTID")
private long relInvstid;
#Column(name="MUTATION_ID")
private long mutationId;
}
Is there any delete methos available in spring data Jpa to delete based on only two of the embaddable key(toInst,relInvstid).
I still can write a JPQL query to delete it. My question is there any method available for this.
like deleteById ?
Yes there is, repo.deleteByIdToInstAndIdRelInvstid(toInst,relInnvstid)
As you see you have to specify deleteByIdToInst , this is how you reference a field of an embedded ID , the same as you would reference a field of a foreign relation. Here Id matches your field naming
#EmbeddedId
private LabResHivMutationPK id;
There are two ways to delete an entity: either using its own "JPA Repository derived delete method" long deleteByFirstIdAndSecondId(long firstId , secondId)
In your service you can simply call it : repository.deleteByFirstIdAndSecondId(long firstId , secondId)
Another way is through the parent entity by excluding the child entity (or entities depends on the relation type).
User underscore '_' when entity will have multiple keys with using #Embedded keys.
example :repository.deleteByid_toInst();

Is it possible to use EF4.2 Code First and Inverse Property Attribute on the same named property?

I want to know if there is a way to achieve a related list of the same entity on the same class or use migrations to setup a model with this attribute in it?
public class Person
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
[InverseProperty("FamilyMembers")]
public List<Person> FamilyMembers { get; set; }
}
At the moment when I am using migrations (AddMigration) to setup the database I get the following exception:
Add-Migration : A relationship cannot be established from property
'FamilyMembers' on type 'ConsoleApplication3.Person' to property
'FamilyMembers' on type 'ConsoleApplication3.Person'. Check the values
in the InversePropertyAttribute to ensure relationship definitions
are unique and reference from one navigation property to its
corresponding inverse navigation property.
Also I get the same error adding Person's to the People dbset when running the a test app.
var p1 = new Person();
p1.Id = Guid.NewGuid();
p1.Name = "p1";
var p2 = new Person();
p2.Id = Guid.NewGuid();
p2.Name = "p2";
var c = new TestContext();
c.People.Add(p1);
Is there another attribute that is not unique and references the same navigation property?
The simple answer is no. Each end of the relation must have its own navigation property.

Resources