Inheritance in MongoDb: how to request instances of defined type - c#-4.0

This is how I used to utilize inheritance in Entity Framework (POCO):
ctx.Animals // base class instances (all instances)
ctx.Animals.OfType<Cat> // inherited class Cat's instances only
ctx.Animals.OfType<Dog> // inherited class Dog's instances only
This is the only similar way I found in MongoDb (MongoDb reference):
var query = Query.EQ("_t", "Cat");
var cursor = collection.FindAs<Animal>(query);
Note in the latter case I have to deal with discriminator ("_t") and hardcode my class name, that is not quite convenient and looks awful. If I miss the query I got an exception on enumeration attempt. Have I missed something? My suggestion was the document Db which stores objects 'as is' should handle inheritance easily.

Assuming your discriminators are functioning (_t is stored correctly for each document) then I think this is what you are looking for.
var results = collection.AsQueryable<Animal>().OfType<Cat>
Returns only those documents that are of type 'Cat'.

Well, a document db does in fact store objects "as is" - i.e. without the notion of objects belonging to some particular class. That's why you need _t when you want the deserializer to know which subclass to instantiate.
In your case, I suggest you come up with a discriminator for each subclass, instead of relying on the class name. This way, you can rename classes etc. without worrying about a hardcoded string somewhere.
You could do something like this:
public abstract class SomeBaseClass
{
public const string FirstSubClass = "first";
public const string SecondSubClass = "second";
}
[BsonDiscriminator(SomeBaseClass.FirstSubClass)]
public class FirstSubClass { ... }
and then
var entireCollection = db.GetCollection<FirstSubClass>("coll");
var subs = entireCollection.Find(Query.Eq("_t", SomeBaseClass.FirstSubClass));

From your link:
The one case where you must call RegisterClassMap yourself (even without arguments) is when you are using a polymorphic class hierarchy: in this case you must register all the known subclasses to guarantee that the discriminators get registered.
Register class maps for your base class and each one of your derived classes:
BsonClassMap.RegisterClassMap<Animal>();
BsonClassMap.RegisterClassMap<Cat>();
BsonClassMap.RegisterClassMap<Dog>();
Make sure that your collection is of type of your base class:
collection = db.GetCollection<Animal>("Animals");
Find using your query. The conversion to the corresponding child class is done automatically:
var query = Query.EQ("_t", "Cat");
var cursor = collection.Find(query);

If the only concern is hardcoding class name, you can do something like this:
collection = db.GetCollection<Animal>("Animals");
var query = Query.EQ("_t", typeof(Cat).Name);
var cursor = collection.Find(query);

Take a look on the documentation
http://docs.mongodb.org/ecosystem/tutorial/serialize-documents-with-the-csharp-driver/#scalar-and-hierarchical-discriminators
The main reason you might choose to use hierarchical discriminators is because it makes it possibly to query for all instances of any class in the hierarchy. For example, to read all the Cat documents we can write:
var query = Query.EQ("_t", "Cat");
var cursor = collection.FindAs<Animal>(query);
foreach (var cat in cursor) {
// process cat
}

Related

Mapping Entity-to-DTO (and vice-versa) in Nest.js

I'm building an API with Nest.js and I've been using a mapper to convert the TypeORM entity to a DTO (and vice-versa).
Until now, I've been doing this manually:
public static async entityToDto(entity: UserEntity): Promise<UserDto> {
const dto = new UserDto();
dto.id = entity.id;
dto.emailAddress = entity.emailAddress;
dto.firstName = entity.firstName;
dto.lastName = entity.lastName;
dto.addressLine1 = entity.addressLine1;
dto.addressLine2 = entity.addressLine2;
dto.townCity = entity.townCity;
[...]
return dto;
}
In my opinion, this is a nice (albeit inflexible) approach. It explicitly controls which fields are returned to the user, minimizing the chance of leaking sensitive fields (like password hash). However, I was under the impression that the purpose of a DTO is to have a single place to modify data about something. If I needed to add a field, I'd have to modify both the DTO and the mapper.
It seems to be the convention to have one mapper per entity. However, if I don't want to return, for example, the accountStatus field, I would have to write a new mapper. So I have now multiple mappers which would need to be modified.
I had the idea to write a "universal" mapper which looks at the fields in the DTO, and maps them to the fields in the entity.
I'm relatively new to TypeScript and Nest.js, so I was wondering how others manage this.
I suggest you should try object property map built-in by typescript. Basically, your entity can be map to dto based on the similar property name like below
public static async entityToDto(entity: UserEntity): Promise<UserDto> {
const dto : UserDTO = ({
...entity,
additionalProperty: entity.someProperty
});
return dto;
}
Any property that sharing the same name between DTO and Entity will be mapped. It is far more clean and more flexible.

DDD: Instantiate Value objects inside Aggregate or pass it as parameter?

When creating aggregates, should we create value objects inside aggregates, or we should pass already created value objects to ctor or factory.
public Booking(DateTime arrivalDate, DateTime departureDate)
{
this.ArrivalAndDepartureinformation = new ArrivalAndDepartureInfo(arrivalDate, departureDate);
}
or
public Booking(ArrivalAndDepartureinformation arrivalAndDepartureInfo)
{
this.ArrivalAndDepartureinformation = arrivalAndDepartureInfo;
}
Instantiate Value objects inside Aggregate or pass it as parameter?
If we speak about passing parameters into constructor, it depends on how it is used. There might be some infrastructure limitations that can require usage of primitive types.
If we speak about passing parameters into methods then Value Objects is 100% my choice.
In general, I'd say it is better to pass value objects into your aggregates.
Value Objects can:
make language of you model more expressive
bring type safety
encapsulate validation rules
own behavior
The general guideline I would recommend is this:
Inside the domain model, use value objects as much as possible.
Convert primitives into value objects at the boundary of the domain model (controllers, application services).
For example, instead of this:
public void Process(string oldEmail, string newEmail)
{
Result<Email> oldEmailResult = Email.Create(oldEmail);
Result<Email> newEmailResult = Email.Create(newEmail);
if (oldEmailResult.Failure || newEmailResult.Failure)
return;
string oldEmailValue = oldEmailResult.Value;
Customer customer = GetCustomerByEmail(oldEmailValue);
customer.Email = newEmailResult.Value;
}
Do this:
public void Process(Email oldEmail, Email newEmail)
{
Customer customer = GetCustomerByEmail(oldEmail);
customer.Email = newEmail;
}
The domain model should speak domain, not implementation primitives.
Your application component normally owns the responsibility of taking raw data and expressing it in the model's language.

Trivial deserialization failing with YamlDotNet

What can possible go wrong with this:
public void Main()
{
var input = new StringReader(Document);
var deserializer = new Deserializer(namingConvention: new CamelCaseNamingConvention());
var p = deserializer.Deserialize<Person>(input);
Console.WriteLine(p.Name);
}
public class Person
{
public string Name {get;set;}
}
private const string Document = #"Name: Peter";
A serialization exception is thrown:
Property 'Name' not found on type 'YamlDotNet.Samples.DeserializeObjectGraph+Person'
The same happens if I first serialize a Person object using the Serializer.
While the online sample for deserialization works just fine - this trivial code does not. What am I missing? It must be a stupid little detail. (But it happened before with other data structures I tried.)
As it seems, the problem is with the namingConvention parameter. If I don't set it to an instance of CamelCaseNamingConvention all is fine.
Unfortunately the "canonical" example (https://dotnetfiddle.net/HD2JXM) uses it and thus suggests it is important.
For any reason the CamelCaseNamingConvention converts the fields to lowercase in the class (ie. 'Name' to 'name'). As the string is 'Name' and not 'name' the deserialization fails. The example uses lower-case therefore it works....
I had the same problem....

How to implement inheritance in Node.JS

How do we use 'inheritance' in Node.JS? I heard that prototype is similar to interfaces in java. But I have no idea how to use it!
Although there are various ways of performing inheritance and OO in javascript, in Node.js you would typically use the built in util.inherits function to create a constructor which inherits from another.
See http://book.mixu.net/ch6.html for a good discussion on this subject.
for example:
var util = require("util");
var events = require("events");
function MyOwnClass() {
// ... your code.
}
util.inherits(MyOwnClass, events.EventEmitter);
Creating an object constructor in pure JS:
They're just functions like any other JS function but invoked with the new keyword.
function Constructor(){ //constructors are typically capitalized
this.public = function(){ alert(private); }
var private = "Untouchable outside of this func scope.";
}
Constructor.static = function(){ alert('Callable as "Constructor.static()"'); }
var instance = new Constructor();
Inheritance:
function SubConstructor(){
this.anotherMethod(){ alert('nothing special'); }
}
function SubConstructor.prototype = new Constructor();
var instance = new SubConstructor();
instance.public(); //alerts that private string
The key difference is that prototypal inheritance comes from objects, rather than the things that build them.
One disadvantage is that there's no pretty way to write something that makes inheritance of instance vars like private possible.
The whopping gigantor mega-advantage, however, is that we can mess with the prototype without impacting the super constructor, changing a method or property for every object even after they've been built. This is rarely done in practice in higher-level code since it would make for an awfully confusing API but it can be handy for under-the-hood type stuff where you might want to share a changing value across a set of instances without just making it global.
The reason we get this post-instantiated behavior is because JS inheritance actually operates on a lookup process where any method call runs up the chain of instances and their constructor prototype properties until it finds the method called or quits. This can actually get slow if you go absolutely insane with cascading inheritance (which is widely regarded as an anti-pattern anyway).
I don't actually hit prototype specifically for inheritacne a lot myself, instead preferring to build up objects via a more composited approach but it's very handy when you need it and offers a lot of less obvious utility. For instance when you have an object that would be useful to you if only one property were different, but you don't want to touch the original.
var originInstance = {
originValue:'only on origin',
theOneProperty:'that would make this old object useful if it were different'
}
function Pseudoclone(){
this.theOneProperty = "which is now this value";
}
Pseudoclone.prototype = originInstance;
var newInstance = new Psuedoclone();
//accesses originInstance.originValue but its own theOneProperty
There are more modern convenience methods like Object.create but only function constructors give you the option to encapsulate private/instance vars so I tend to favor them since 9 times out of 10 anything not requiring encapsulation will just be an object literal anyway.
Overriding and Call Object Order:
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
instance.myMethod = function(){ alert(private); }
instance.myMethod();//"undefined"
Note: the parens around the constructor allow it to be defined and evaluated in one spot so I could treat it like an object on the same line.
myMethod is alerting "undefined" because an externally overwritten method is defined outside of the constructor's closure which is what effective makes internal vars private-like. So you can replace the method but you won't have access to what it did.
Now let's do some commenting.
( function Constructor(){
var private = "public referencing private";
this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"public referencing private"
and...
( function Constructor(){
var private = "public referencing private";
//this.myMethod = function(){ alert(private); }
} ).prototype = { myMethod:function(){ alert('prototype'); };
var instance = new Constructor();
//instance.myMethod = function(){ alert(private); }
instance.myMethod();//"prototype"
Note that prototype methods also don't have access to that internal private var for the same reason. It's all about whether something was defined in the constructor itself. Note that params passed to the constructor will also effectively be private instance vars which can be handy for doing things like overriding a set of default options.
Couple More Details
It's actually not necessary to use parens when invoking with new unless you have required parameters but I tend to leave them in out of habit (it works to think of them as functions that fire and then leave an object representing the scope of that firing behind) and figured it would be less alien to a Java dev than new Constructor;
Also, with any constructor that requires params, I like to add default values internally with something like:
var param = param || '';
That way you can pass the constructor into convenience methods like Node's util.inherit without undefined values breaking things for you.
Params are also effectively private persistent instance vars just like any var defined in a constructor.
Oh and object literals (objects defined with { key:'value' }) are probably best thought of as roughly equivalent to this:
var instance = new Object();
instance.key = 'value';
With a little help from Coffeescript, we can achieve it much easier.
For e.g.: to extend a class:
class Animal
constructor: (#name) ->
alive: ->
false
class Parrot extends Animal
constructor: ->
super("Parrot")
dead: ->
not #alive()
Static property:
class Animal
#find: (name) ->
Animal.find("Parrot")
Instance property:
class Animal
price: 5
sell: (customer) ->
animal = new Animal
animal.sell(new Customer)
I just take the sample code Classes in CoffeeScript. You can learn more about CoffeeScript at its official site: http://coffeescript.org/

ektorp / CouchDB mix HashMap and Annotations

In jcouchdb I used to extend BaseDocument and then, in a transparent manner, mix Annotations and not declared fields.
Example:
import org.jcouchdb.document.BaseDocument;
public class SiteDocument extends BaseDocument {
private String site;
#org.svenson.JSONProperty(value = "site", ignoreIfNull = true)
public String getSite() {
return site;
}
public void setSite(String name) {
site = name;
}
}
and then use it:
// Create a SiteDocument
SiteDocument site2 = new SiteDocument();
site2.setProperty("site", "http://www.starckoverflow.com/index.html");
// Set value using setSite
site2.setSite("www.stackoverflow.com");
// and using setProperty
site2.setProperty("description", "Questions & Answers");
db.createOrUpdateDocument(site2);
Where I use both a document field (site) that is defined via annotation and a property field (description) not defined, both get serialized when I save document.
This is convenient for me since I can work with semi-structured documents.
When I try to do the same with Ektorp I have documents using annotations and Documents using HashMap BUT I couldn't find an easy way of getting the mix of both (I've tried using my own serializers but this seems to much work for something that I get for free in jcouchdb). Also tried to annotate a HashMap field but then is serialized as an object and I get the fields automatically saved BUT inside an object with the name of the HashMap field.
Is it possible to do (easily/for free) using Ektorp?
It is definitely possible. You have two options:
Base your class on org.ektorp.support.OpenCouchDbDocument
Annotate the you class with #JsonAnySetter and #JsonAnyGetter. Red more here: http://wiki.fasterxml.com/JacksonFeatureAnyGetter

Resources