How can I save entities with geometric properties (like NTS) with mongo db?
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
public class Area
{
public string Id { get; set; }
public Polygon Extent { get; set; }
}
When I try to save the object I get the
"Maximum serialization depth exceeded (does the object being serialized have a circular reference?)."
exception (NTS does have circular references in its objects). Is there a way to by pass it?
Yes, you can write a custom serializer. Such serializers are also included in the C# driver code itself, for instance in the CultureInfoSerializer (.NET Culture Infos have cyclic references, plus you only want to store the actual locale code, not all the derived information).
The source code of the CultureInfoSerializer is pretty straightforward.
For those still looking for a solution, I have created MongoDB.NetTopologySuite.Serialization package which adds support for serializing/deserializing NetTopologySuite models to BSON and back.
Related
I have searched every way I can think of for the answer to this, so forgive me if I have overlooked a post...
I have a project containing model classes that I want to remain database-ignorant (pretend someone handed me the code and said "you're not allowed to modify one character of these classes"). I want to persist these to SQL Server using Entity Framework. So far, I have been able to use the fluent API to map anything that EF couldn't determine logically. But I have hit a block with the following:
public class PhotoPost {
// mapped as Key with fluent API - comes from blog provider
public string PostID { get; set; }
public string Caption { get; set; }
public Collection<Photo> Photos { get; set; }
}
public class Photo {
public string Url { get; set; }
public Image LoadImage() { … }
}
I have a class, PhotoPost, which represents a type of Post on a Blog. The PhotoPost instance has a collection of objects of type Photo, all of which need to be persisted to the database. My problem is that the Photo doesn't really have a primary key. Blog provider doesn't guarantee the Url will not change, and I can't touch this code to add an arbitrary ID. Furthermore, I don't really want an ID. The code that is going to interact with these objects shouldn't/won't know whether these objects came from the blog's API or from a local database (or XML, ...), so I don't really want to clutter up my code with boilerplate in subclassing these objects in another project just to add IDs everywhere (and constructors to create subclasses with IDs from parent classes without, as above) to make EF happy.
Is subclassing to add IDs my only option, or is there a way that I can meet in the middle, between "entity" and "complex type"? (From what I understand, complex types must be one-to-one with their parent entities.)
I really want to be able to use NodaTime in my Entity Framework Code First database projects but haven't found a "clean" way to do it. What I really want to do is this:
public class Photoshoot
{
public Guid PhotoshootId{get; set;}
public LocalDate ShootDate{get; set;} //ef ignores this property
}
Is there any supported or recommended approach to using NodaTime with EF Code First?
Until custom primitive type persistence is natively supported in Entity Framework, a common work around is to use buddy properties.
For each custom primitive within your domain model, you create an associated mapped primitive to hold the value in a format supported by Entity Framework. The custom primitive properties are then calculated from the value of their corresponding buddy property.
For example:
public class Photoshoot
{
// mapped
public Guid PhotoshootId{get; set;}
// mapped buddy property to ShootDate
public DateTime ShootDateValue { get; set; }
// non-mapped domain properties
public LocalDate ShootDate
{
get { // calculate from buddy property }
set { // set the buddy property }
}
}
We use NodaTime in our code first POCO's using exactly this approach.
Obviously this leaves you with a single type acting as both a code first POCO and a domain type. This can be improved at the expense of complexity by separating out the different responsibilities into two types and mapping between them. A half-way alternative is to push the domain properties into a subtype and make all mapped buddy properties protected. With a certain amount of wanging Entity Framework can be made to map to protected properties.
This rather splendid blog post evaluates Entity Framework support for various domain modelling constructs including encapsulated primitives. This is where I initially found the concept of buddy properties when setting up our POCO's:
http://lostechies.com/jimmybogard/2014/04/29/domain-modeling-with-entity-framework-scorecard/
A further blog post in that series discusses mapping to protected properties: http://lostechies.com/jimmybogard/2014/05/09/missing-ef-feature-workarounds-encapsulated-collections/
EF Core 2.1 has a new feature Value Conversions, which is exactly for this scenario.
//OnModelCreating
builder.Entity<MyEntity>
.Property(e => e.SomeInstant)
.HasConversion(v => v.ToDateTimeOffset(), v => Instant.FromDateTimeOffset(v));
.HasConversion has some other overloads to make this logic re-useable, for example you can define your own ValueConverter.
No "clean" way that I'm aware of because EF, as of this writing, doesn't have a mechanism for simple type conversion like you see in NHibernate (IUserType). A real limitation in EF as an ORM which causes me to change my domain to suit my ORM.
There is a provider specific way that works with Postgres (Npgsql).
Install the library
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime
And then while configuring DbContext, use this,
services.AddDbContext<PhotoshootDbContext>(opt =>opt.UseNpgsql(Configuration.GetConnectionString("ConnectionString"), o => o.UseNodaTime()));
There are some third party libraries for other providers too.
Is it possible to have Code First data classes declared with internal access as shown:
internal class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
I have a requirement that classes and its properties should not be visible outside of the assembly.
As long as your DbContext derived class that exposes your class to EF is in the same assembly, you should be able to. I don't happen to design my apps that way as I prefer more separation. But the context should be able to build the model and it should be able to interact with the classes (e.g. execute queries, save changes etc) if they are in the same assembly since it will have access to the internal class. Even with the various odd things we tried and wrote about in the Code First book, I never happened to try this particular scenario.
I want a list of different (derived) object types working with the Default Modelbinder in Asp.net MVC 2.
I have the following ViewModel:
public class ItemFormModel
{
[Required(ErrorMessage = "Required Field")]
public string Name { get; set; }
public string Description { get; set; }
[ScaffoldColumn(true)]
//public List<Core.Object> Objects { get; set; }
public ArrayList Objects { get; set; }
}
And the list contains objects of diffent derived types, e.g.
public class TextObject : Core.Object
{
public string Text { get; set; }
}
public class BoolObject : Core.Object
{
public bool Value { get; set; }
}
It doesn't matter if I use the List or the ArrayList implementation, everything get's nicely scaffolded in the form, but the modelbinder doesn't resolve the derived object type properties for me when posting back to the ActionResult.
What could be a good solution for the Viewmodel structure to get a list of different object types handled? Having an extra list for every object type (e.g. List, List etc.) seems to be not a good solution for me, since this is a lot of overhead both in building the viewmodel and mapping it back to the domain model.
Thinking about the other approach of binding all properties in a custom model binder, how can I make use the data annotations approach here (validating required attributes etc.) without a lot of overhead?
Check out the Derived Type ModelBinder in MvcContrib. This allows you to modelbind to derived types through the process of 'typestamping' - which is handled automatically for you when using the RenderTypedPartial(...) helper. MvcContrib partials maintain binding state across partials so the Name/Id prefixes are properly maintained on a deep object graph. If you use other mechanisms like templates, then you'll need to handle the typestamping yourself. This is explained in the documentation page.
Getting back to your questions and how the derived types are resolved with the ModelBinder, you can register the derived type variations with attributes in a mechanism similar to the WCF KnownTypeAttribute or you can do the registration on startup. Either way, these variations are registered once and held onto for performance considerations.
The model binder also solves this problem in a way that does not interfere with data annotation/validation attributes. They will work as you expect them in any other scenario.
This is what reflector gives:
public int Int1 { get; set; }
public string StringA { get; set; }
// Fields
[CompilerGenerated]
private int <Int1>k__BackingField;
[CompilerGenerated]
private string <StringA>k__BackingField;
The problem is that C# specification doesn't explicitly specify how backing fields for automatic properties are named.
This can be a problem for binary serialization (from book C# 3.0 in a Nutshell).
Are there any other problems with auto-properties ? Should MS specify this in C# specs ?
I don't think MS should specify a name - I think it's more reasonable to avoid binary serialization, which is always going to be somewhat brittle in my opinion. (Java serialization is similarly brittle.) If it relies on field names (and there may be a way of getting round that by attributing your properties - I'm not sufficiently experienced with binary serialization to know) then it's restricting implementation changes quite nastily already.
My biggest problem with automatic properties is that there's no way of creating genuinely readonly properties (with readonly backing fields). I've ranted about this before though...
I don't like the following about auto-properties:
It is not possible to place break points on auto-properties.
The fields in the class are obvious, you will have to examine the fields as well as the properties to know what are the fields in the class. Where if they are not used, then you can just inspect the fields region.
Removes the ability to decorate the underlying fields with readonly, volatile, etc.