I'm starting to use Realm to store objects in my Android app. Here's an example of what I'm looking to store:
public class Item implements RealmModel {
String id;
...
}
I have multiple lists that display items. The number of lists can keep expanding (the user can create as many lists as possible.
Let's say the user create's a list called "Best". When I'm viewing the "Best" list I call getItems("Best") which gets a List<Items> from the API. I now have to figure out how to store this list. In SQLite world I would have create a new table "custom_list_best", for example, which is just a single list of all the Item.id's that are part of the list. I would also have an "items" table that has all the distinct Items. To get items in the best list I would simply do a join query on both the best and items tables.
In the Realm world I'm trying to figure out how Realm works and what's the best way to build my models.
I initially thought I could create an object called CustomList:
public class CustomList implements RealmModel {
String listId;
RealmList<Item> items;
}
I would then store a RealmList<CustomList>. But the only issue is I also want to be able to query against all Items. So I need to also store a RealmList<Item> in Realm. How does Realm work in this case? If I store a separate RealmList<Item> and then store each RealmList<CustomList> will it not duplicate data?
Instead will I have to manually handle this by doing this instead:
public class CustomList implements RealmModel {
String listId;
List<String> itemIds;
}
And then query for Item.class objects that have itemId in itemIds from above object?
In SQLite world I would have create a new table "custom_list_best",
No, you would have a table called custom_lists with an auto-increment ID and an identifier, and a join table called join_custom_lists_items that would contain the ID of custom_lists and the ID of any item that belongs to that given custom list.
In the Realm world I'm trying to figure out how Realm works and what's the best way to build my models.
If the ID of the item is concrete and you need to be able to store the same Item in multiple lists, then in order to access the lists in both directions, you'll need a RealmList<? extends RealmModel> in both cases.
#RealmClass
public class Item implements RealmModel {
#PrimaryKey
private String id;
private RealmList<CustomList> customLists;
// getter setter
}
And
#RealmClass
public class CustomList implements RealmModel {
#PrimaryKey
private String title; // assuming you cannot name two lists the same? otherwise do `#Index`
private RealmList<Item> items;
// getter setter
}
This way you can do
realm.executeTransaction(new Realm.Transaction() {
public void execute(Realm realm) {
Item item = realm.where(Item.class).equalTo(ItemFields.ID, itemId).findFirst(); // assuming exists
CustomList customList = realm.where(CustomList.class).equalTo(CustomListFields.TITLE, "Best").findFirst();
if(customList == null) {
customList = realm.createObject(CustomList.class, "Best");
}
customList.getItems().add(item);
item.getCustomLists().add(customList);
}
}
And then you can query
RealmResults<Item> bestItems = realm.where(Item.class)
.equalTo(ItemFields.CustomLists.TITLE, "Best")
//same as "customLists.title"
.findAll();
All this Fields stuff I'm using is from https://github.com/cmelchior/realmfieldnameshelper
Related
I get data from my database (Firebase database). This is a document with several data, including a Array with GeoPoint fields.
var documents = await CrossCloudFirestore.Current .Instance .Collection("Activity") .GetAsync();
My object is defined like this in my Model class: public class Activity { public object elapsedTime { get; set; } public object positions { get; set; } ...... }
It works. I can have the data on my Activity class.
However, I would like to know how I can access this data because foreach loops do not work for object types. Maybe I need to redefine my Activity Class ?
Thx :=)
Edit :
You can see here my firebase :
And then the result of the request :
In your scenario , the property is dynamic for each object , I would suggest you deserialize the root level as a dictionaryand then get the data you want .
Items = JsonConvert.DeserializeObject<Dictionary<string, YourClass>>(content).Values.ToList()
Oh before this, Newtonsoft plugin is required .
Refer to
Deserialize JSON into readable format
It works ! :)
To do it, I defined Array (from firestore) as IEnumerable on my C# class, with the same name from firestore to c#.
And then, here is my query and the line to get my objects converted.
I'd like to add a derived list to a DTO/model object when mapping from an entity. For example, I have an entity class named Company that has a list of Employees. I'd like for the Company Model object to contain the list of Employees as well as a list of Employees who are Managers. (This is not my actual class names, but this type of thing is what I'm trying to do). So, I want the Company DTO to have a list of Employees and a list of Managers where the Managers is a subset of Employees that is derived by filtering the list of Employees.
I tried using a mapping expression and a default method. However, I need to use the EmployeeMapper and it seems that I don't have access to the mapper.
Here's what I tried...
#Mapper(componentModel = "spring", uses = {EmployeeMapper.class})
public interface CompanyMapper extends IEntityMapper<CompanyModel, Entity> {
#Mapping(expression = "java(deriveManagers(model))", target = "managers")
EntityModel toModel(Company company);
default List<EmployeeModel> deriveManagers(Company company) {
List<EmployeeModel> managers = new ArrayList<EmployeeModel>();
company.getEmployees().forEach(nextEmployee -> {
if (nextEmployee.getJobTitle().equals(JobTitle.MANAGER)) {
managers.add(this.EmployeeMapper.toModel(nextEmployee);
}
});
return managers;
}
}
I decided to do this processing in the DTO/Model object rather than in the Mapper. The list can be derived as a subset of the EmployeeModel objects in the CompanyModel object. Therefore, I think that this is the right place to derive this list. It is not really a mapping from Entity to Model object as much as it is a derived attribute in the Model object.
Here is my entity class:
public class User {
#Id
UserIdentifier userIdentifier;
String name;
}
public class UserIdentifier {
String ssn;
String id;
}
Here is what I am trying to do:
public interface UserRepository extends MongoRepository<User, UserIdentifier>
{
User findBySsn(String ssn);
}
I get an exception message (runtime) saying:
No property ssn found on User!
How can I implement/declare such a query?
According to Spring Data Repositories reference:
Property expressions can refer only to a direct property of the managed entity, as shown in the preceding example. At query creation time you already make sure that the parsed property is a property of the managed domain class. However, you can also define constraints by traversing nested properties.
So, instead of
User findBySsn(String ssn);
the following worked (in my example):
User findByUserIdentifierSsn(String ssn);
I have a GridView which needs to page and sort data which comes from a collection of Customer objects.
Unfortunately my customer information is stored separately...the customer information is stored as a Customer ID in my database, and the Customer Name in a separate DLL.
I retrieve the ID from the database using Entity Framework, and the name from the external DLL through a partial class.
I am getting the ID from my database as follows:
public class DAL
{
public IEnumberable<Customer> GetCustomers()
{
Entities entities = new Entities();
var customers = (from c in entities.Customers
select c);
//CustomerID is a field in the Customer table
return customers;
}
}
I have then created a partial class, which retrieves the data from the DLL:
public partial class Customer
{
private string name;
public string Name
{
if (name==null)
{
DLLManager manager = new DLLManager();
name= manager.GetName(CustomerID);
}
return name;
}
}
In my business layer I can then call something like:
public class BLL
{
public List<Customer> GetCustomers()
{
DAL customersDAL = new DAL();
var customers = customersDAL.GetCustomers();
return customers.ToList();
}
}
...and this gives me a collection of Customers with ID and Name.
My problem is that I wish to page and sort by Customer Name, which as we have seen, is populated from a DLL. This means I cannot page and sort in the database, which is my preferred solution. I am therefore assuming I am going to have to call of the database records into memory, and perform paging and sorting at this level.
My question is - what is the best way to page and sort an in-memory collection. Can I do this with my List in the BLL above? I assume the List would then need to be stored in Session.
I am interested in people's thoughts on the best way to page and sort a field that does not come from the database in an Entity Framework scenario.
Very grateful for any help!
Mart
p.s. This question is a development of this post here:
GridView sorting and paging Entity Framework with calculated field
The only difference here is that I am now using a partial class, and hopefully this post is a little clearer.
Yes, you can page and sort within you list in the BLL. As long as its fast enough I wouldn't care to much about caching something in the session. An other way would be to extend your database with the data from you DLL.
I posted this question slightly differently on a different forum, and got the following solution.
Basically I return the data as an IQueryable from the DAL which has already been forced to execute using ToList(). This means that I am running my sorting and paging against an object which consists of data from the DB and DLL. This also allows Scott's dynamic sorting to take place.
The BLL then performs OrderBy(), Skip() and Take() on the returned IQueryable and then returns this as a List to my GridView.
It works fine, but I am slightly bemused that we are perfoming IQueryable to List to IQueryable to List again.
1) Get the results from the database as an IQueryable:
public class DAL
{
public IQueryable<Customer> GetCustomers()
{
Entities entities = new Entities();
var customers = (from c in entities.Customers
select c);
//CustomerID is a field in the Customer table
return customers.ToList().AsQueryable();
}
}
2) Pull the results into my business layer:
public class BLL
{
public List<Customer> GetCustomers(intint startRowIndex, int maximumRows, string sortParameter)
{
DAL customersDAL = new DAL();
return customersDAL.GetCustomers().OrderBy(sortParameter).Skip(startRowIndex).Take(maximumRows).ToList();
}
}
Here is the link to the other thread.
http://forums.asp.net/p/1976270/5655727.aspx?Paging+and+sorting+Entity+Framework+on+a+field+from+Partial+Class
Hope this helps others!
I have a domain object which has a collection of primitive values, which represent the primary keys of another domain object ("Person").
I have a Wicket component that takes IModel<List<Person>>, and allows you to view, remove, and add Persons to the list.
I would like to write a wrapper which implements IModel<List<Person>>, but which is backed by a PropertyModel<List<Long>> from the original domain object.
View-only is easy (Scala syntax for brevity):
class PersonModel(wrappedModel: IModel[List[Long]]) extends LoadableDetachableModel[List[Person]] {
#SpringBean dao: PersonDao =_
def load: List[Person] = {
// Returns a collection of Persons for each id
wrappedModel.getObject().map { id: Long =>
dao.getPerson(id)
}
}
}
But how might I write this to allow for adding and removing from the original List of Longs?
Or is a Model not the best place to do this translation?
Thanks!
You can do something like this:
class PersonModel extends Model<List<Person>> {
private transient List<Person> cache;
private IModel<List<String>> idModel;
public PersonModel( IModel<List<String>> idModel ) {
this.idModel = idModel;
}
public List<Person> getObject() {
if ( cache == null ) {
cache = convertIdsToPersons( idModel.getObject() );
return cache;
}
public void setObject( List<Person> ob ) {
cache = null;
idModel.setObject( convertPersonsToIds( ob ) );
}
}
This isn't very good code but it shows the general idea. One thing you need to consider is how this whole thing will be serialised between requests, you might be better off extending LoadableDetachableModel instead.
Another thing is the cache: it's there to avoid having to convert the list every time getObject() is called within a request. You may or may not need it in practice (depends on a lot of factors, including the speed of the conversion), but if you use it, it means that if something else is modifying the underlying collection, the changes may not be picked up by this model.
I'm not quite sure I understand your question and I don't understand the syntax of Scala.
But, to remove an entity from a list, you can provide a link that simply removes it using your dao. You must be using a repeater to populate your Person list so each repeater entry will have its own Model which can be passed to the deletion link.
Take a look at this Wicket example that uses a link with a repeater to select a contact. You just need to adapt it to delete your Person instead of selecting it.
As for modifying the original list of Longs, you can use the ListView.removeLink() method to get a link component that removes an entry from the backing list.