Realm net: sort by linked collection alternative - xamarin

I have realm object Item with linked collection Properties:
public class Item : RealmObject
{
public IList<Property> Properties { get; }
public int Id {get; set;}
....
}
public class Property : RealmObject
{
public string Key {get; set;}
public string Value {get; set;}
}
And I need to sort to Item entities by properties from linked Properties collection.
Something like this (I know it's not supported by Realm):
Realm.All<Item>().OrderBy(f => f.Properties.FirstOrDefault( p => p.Key == "Status").Value)
It is not possible to move properties to Item entity cause different items can contain different properties set which also may change over time.
Is there other options to implement this kind of sorting? For now I see only option to sort objects in memory, but it may take too much memory on big dataset.

This is not yet possible, I'm afraid.
We're going to be working on many LINQ improvements soon, but this particular request is on the complex side so it probably won't be something we will be able to offer in the near future.

Related

EF, POCO, DB First... how to do Business Logic in Property "set"?

OK, so I've been building my first large(ish) EF 4.1 POCO + MVC application. It's a replacement of a legacy system so I 'm using an existing database.
I've generated my POCO classes using DbContext T4 generation. I've got some really nice forms going on and some really nice validation happening with a lot of sexy generics in my MVC classes to cut down on boiler-plate code... All's good.
Suddenly I realized that the most sensible thing (to me) would be for some of business logic to be in the "set" of some of the properties of my POCO objects.
E.g. Suppose the following class was generated by the T4;
public partial class SalesOrderLine
{
public int ID { get; set; }
public int SalesOrderID { get; set; }
public int ProductID { get; set; }
public decimal UnitPrice { get; set; }
public int Quantity { get; set; }
public decimal ExtendedPrice { get; set; }
public virtual Product Product { get; set; }
public virtual SalesOrder SalesOrder { get; set; }
}
Ignore for a moment the obvious argument that the calculated field "ExtendedPrice" shouldn't even be stored in the database, and just come along with me for the ride...
...then, it seems to me, logically, if this object is really supposed to represent a Sales Order Line, that I should be able to construct my object such that the following unit test will work:
SalesOrderLine sol = new SalesOrderLine();
sol.UnitPrice = 100;
sol.Quantity = 5;
Assert.IsEqual(sol.ExtendedPrice, 500);
...obviously I can't do that as long as I want the base POCO to be generated by the T4. It seems to me I have several options:
Set the generated code file's properties "do not compile", copy and paste the generated code into another file and modify the "set" to do the business logic of setting the extended price when the UnitPrice or Quantity is set. The downside here is that the logic will be run whenever an object is loaded from the database (since the EF will set the public properties and not my private fields). Additionally, this object will then need to be maintained manually for the rest of the life of the project when database changes occur.
Create an UpdateTotals function that gets called in the Validate routine that I have for my object, which gets called by the SaveChanges() on the DbContext. Obviously, the above Unit Test above would not work in that case. The system, and my integration tests however would work and would only call the code when a change was done to the object.
Decide that I'm asking the wrong question, and that I should really add methods to the object called "SetPrice" and "SetQuantity", and then qualify the set accessors of the UnitPrice and Quantity to be "internal". The downside here is that MVC will try and update the model from the form and won't be able to set those properties.
Some solution that involves downloading two or three more frameworks that create even more levels of abstraction than I already have... A repository pattern, or "use NHibernate" or something like that... You can suggest this, but I'm growing weary of how much work it is to set things up to do it the "academically correct" way. For this project, I'd rather meet halfway on the long-term-maintainability vs. speed-of-development spectrum and not over-complicate my project with a ton of extra tools and dlls... ...but I'll try an keep an open mind :)
--- EDIT: another idea ---
[5.] Another thought, since the fields are always simply calculated there should really be no need to ever set them - either from the database or otherwise. Therefore, something like this might work:
public decimal ExtendedAmount
{
get { return UnitPrice * Quantity; }
internal set { }
}
...my thought is that the EF instantiation would attempt to call the "set", but the set would do nothing, then, when the object was saved or checked for changes it would call the 'get' and that would return the calculated value and that value would get stored in the DB. The only downside here is when you were trying to use the object model to validate the database when the database had in incorrect value stored in the ExtendedAmount field. It's a little hokie, I know, but I thought it would be an interesting trick... in fact the "set" could perhaps throw an exception if (value != UnitPrice * Quantity)
--- END EDIT ---
I'm curious to hear what other have done in these kinds of cases, as I'm sure it's common. Seems like a lot of the tutorials take you as far as "generating POCO classes from the database", and then leave the rest of the project development up to you.
Cheers,
Chris
A couple ideas:
Why not use Code First? That way, you can put business logic (e.g., calculated properties) right in your entity class.
Example
public partial class SalesOrderLine
{
public int ID { get; set; }
public int SalesOrderID { get; set; }
public int ProductID { get; set; }
private decimal _unitPrice;
public decimal UnitPrice
{
get { return _unitPrice; }
set
{
if (value == _unitPrice) return;
_unitPrice = value;
CalculateExtendedPrice();
}
}
private decimal _quantity;
public decimal Quantity
{
get { return _quantity; }
set
{
if (value == _quantity) return;
_quantity= value;
CalculateExtendedPrice();
}
}
public decimal ExtendedPrice { get; set; }
public virtual Product Product { get; set; }
public virtual SalesOrder SalesOrder { get; set; }
private void CalculateExtendedPrice()
{
ExtendedPrice = UnitPrice * Quantity;
}
}
If Code First is not an option, what about making your entity a partial class (if it is not already) and putting your business logic in a separate code file (but with the same class name). This way, your main code file will get overwritten when you generate, but your secondary code file will remain. This is the usual way to deal with generated code.

How to make single controller for two database classes - MVC3

I have two database classes as defined below:
public class TopDate
{
[Key]
public int DateId { get; set; }
public DateTime Date { get; set; }
}
public class TopSong
{
[Key]
public int SongId { get; set; }
public string Title { get; set; }
public int DateId { get; set; }
}
where DateId is foreign key to TopSong
I am creating a controller through which i can create, delete or edit these database values.
When i right click on controller class and add controller i can only select one of the two classes defined above. Is there a way to make 1 controller to handle database updates to both these tables on one page?
Error Image:
Your controller should not be dealing directly with domain objects (meaning those things that are directly associated with your database). Create a ViewModel that contains the properties that you need, use your service layer to populate the ViewModel and your controller will use that as the Model for its base. An example of your ViewModel could be something like the following given your description above:
public class MusicViewModel
{
public int SongId {get;set;}
public string Title {get;set;}
public IEnumerable<DateTime> TopDates {get;set;}
}
This view model would contain a list of all dates that a specific song was a Top Song.
The objects you showing (code) are database classes (so called domain objects).
What you need to do is to define a view model, a standard ASP MVC practice:
you define a class, that is tailored for specific view and only containing data relevant to that particular view. So you will have a view model for a view that will create a song, another that will update it etc.
Actually situation you describing is classical situation to use view models. Using domain objects in the views, however, is really really bad practice and prone to more problems than you want to deal with.
Hope this helps.

ASP.Net MVC 3 DataAnnotations validating List<T>

I have a ViewModel that has been deserialized from JSON which looks something like this:
public class UserThingsUpdateViewModel
{
public IList<Thing> Things { get; set; }
[Required]
public int UserId { get; set; }
public int Age { get; set; }
}
Thing is also a ViewModel which also has various DataAnnotaion ValidationAttribute attributes on the properties.
The problem is that Lists don't seem to get validated and even after a through search I cant seem to find any articles that tackle this. Most suggest that the ViewModel is wrong if it includes a list.
So, what is the best way to validate my list and add Model Errors to the Model State?
Prior to checking ModelState.IsValid, you could add code to step through and validate each Thing, as follows:
foreach (var thing in Things)
TryValidateModel(thing);
This will validate each item, and add any errors to ModelState.
You could write a custom validator attribute and decorate the list property with it? That would allow you to write custom logic to get the elements out of the list and validate them.

Serializing EF4.1 Entities using JSON.Net

I am building an application using MVC3, Razor view engine, Repository Pattern with Unit of Work and using EF4.1 Code First to define my data model.
Here is a bit of background (gloss over it if you want).
The application itself is just an Intranet 'Menu'.
The 2 main entities are MenuItem and Department of which:
MenuItem can have many Departments
Departments can have many MenuItems
MenuItem may have a MenuItem as a parent
This is how I have defined my Entities
public class MenuItem
{
public int MenuItemId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual ICollection<Department> Departments { get; set; }
public int? ParentId { get; set; }
public virtual MenuItem ParentMenuItem { get; set; }
}
public class Department
{
public int DepartmentId { get; set; }
public string Name { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
I am using the FluentAPI to define the Self Reference Many-to-Many for the MenuItem.
The issue I am having is passing a MenuItem to the view via JSON.
The central issues are that I have a circular reference between my entities that the built in JSON parser can't deal with and I have lazy loading and proxy generation still enabled.
I am using JSON.net library from Nuget as my JSON Serializer as this seems to be a nice way round the circular reference issue. I now am unsure how to 'fix' the proxy generation issue. Currently the serializer throws The RelationshipManager object could not be serialized. This type of object cannot be serialized when the RelationshipManager belongs to an entity object that does not implement IEntityWithRelationships.
Can anyone help me with this? If I turn off proxy generation, I am going to have a hell of a time loading all of the MenuItem children so I am keen leave this on. I have read a fair amount and there seems to be a variety of different answers including projecting the entities into another object and serialize that, etc, etc. Ideally there would be some way of configuring JSON.net to ignore the RelationshipManager object?
Update
Here is what I have used as a Custom ContractResolver for JSON.Net serializer. This seems to have sorted out my issue.
public class ContractResolver : DefaultContractResolver
{
private static readonly IEnumerable<Type> Types = GetEntityTypes();
private static IEnumerable<Type> GetEntityTypes()
{
var assembly = Assembly.GetAssembly(typeof (IEntity));
var types = assembly.GetTypes().Where(t => String.Equals(t.Namespace, "Namespace", StringComparison.Ordinal));
return types;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
if (!AllowType(objectType))
return new List<MemberInfo>();
var members = base.GetSerializableMembers(objectType);
members.RemoveAll(memberInfo => (IsMemberEntityWrapper(memberInfo)));
return members;
}
private static bool AllowType(Type objectType)
{
return Types.Contains(objectType) || Types.Contains(objectType.BaseType);
}
private static bool IsMemberEntityWrapper(MemberInfo memberInfo)
{
return memberInfo.Name == "_entityWrapper";
}
}
IEntity is an interface all my Code First entity objects implement.
I realise this question has an accepted answer, but I thought I would post my EF Code First solution for future viewers. I was able to get around the error message with the contract resolver below:
class ContractResolver : DefaultContractResolver
{
protected override List<System.Reflection.MemberInfo> GetSerializableMembers(Type objectType)
{
if (objectType.Namespace.StartsWith("System.Data.Entity.Dynamic"))
{
return base.GetSerializableMembers(objectType.BaseType);
}
return base.GetSerializableMembers(objectType);
}
}
This works because EF Code First classes inherit from the POCO class that you actually want serialized, so if we can identify when we are looking at an EF generated class (by checking the namespace) we are able to just serialize using the properties from the base class, and therefore only serialize the POCO properties that we were really after in the first place.
Well, you used powerful serialization API which serializes references and all members as well and now you complains that it serializes all members :)
I didn't test it but I believe this will bring you close to the solution.
JSON.NET is quite powerful tool and it should offer you the extensibility point to avoid this behavior but you will have to code it yourselves. You will need custom DataContractResolver where you define which members should be serialized. Here is the similar example for NHibernate.
You can implement some logic which will take only members present in the parent class of dynamic proxy. I hope this will not break lazy loading. To validate that current entity is proxy you can use this code to get all known proxy types:
IEnumerable<Type> types = ((IObjectContextAdapter)dbContext).ObjectContext.GetKnownProxyTypes();

How do I create collections of sample data in Blend?

Let's say I have a class Person:
public class Person
{
public string Name {get; set;}
public int Age {get; set;}
}
I would like to create some sample data in Blend to help me design my user interface visually. I choose to create sample data based on a class in Blend, but what I get is a sample Person - singular. I want to create a collection of Person to bnd to a list box. How do I tell it to do this? I can't find anywhere where it asks. Do I have to create a class that is a collection of Person. Surely there has to be a way to do this?
Thanks in advance.
I found a way to do this, though not ideal.
The creation of sample data based on a class is a one-time thing. Here's what I did to get my list of Person objects in sample data:
public class Person
{
public string Name {get; set;}
public int Age {get; set;}
}
public class PersonCollection : List<Person> {}
I created the PersonCollection class, which is simply a collection of Person objects. I then created my sample data based on the PersonCollection class - giving me the sample data I was after. I then removed the PersonCollection, leaving the sample data in place.
I'd call this a workaround rather than a solution. If anyone can offer a true solution - a way to do this in Blend without having to create summy classes, I'll be more than happy to mark that as the solution.
You can use data pane->Add sample datasource->Define New Sample Data to do this.

Resources