I am messing around with NHibernate Search and Lucene to create a searchable index of legal entities. My domain model looks somewhat like this:
[Indexed]
public abstract class LegalEntity : AggregateRoot
{
public virtual Address Address { get; set; }
}
public class Person : LegalEntity
{
public virtual string FirstNames { get; set; }
public virtual string LastName { get; set; }
}
public class Company: LegalEntity
{
public virtual string Name { get; set; }
}
public class Address : Component
{
public virtual string Street { get; set; }
public virtual string HouseNumber { get; set; }
// etc...
}
As the subclassing implies, LegalEntity is an NHibernate entity specialized as Person and Company, and Address is an NHibernate component.
Now, how would I best go about creating a really Google-like fuzzy search that includes all the fields of a LegalEntity, including those inside the Address component?
My first idea was to implement an AddressFieldBridge to help in bringing in the fields of the Address component, and then just throw in [Field] on all the fields, but then I could not find a way to construct a FuzzyQuery as a conjuntion between multiple search terms.
My next idea was to create an abstract property tagged with [Field] on LegalEntity, like so:
[Field(Index.Tokenized)]
public abstract string SearchableText { get; }
and then have Person and Company return texts that combine names and all the fields from the Address component into one string, which would then be tokenized and indexed by Lucene.
That, however, made me feel kind of icky.
I would like to learn the best and least intrusive (from a domain model perspective) way to accomplish this task - any suggestions are appreciated :)
Take a look at my question.
Andrey created patch to specify lucene stuff outside. Syntax ain't uber clean (maybe there's some progress done on this, haven't checked), but i guess it gets job done.
Related
I am trying to develop an enterprise-level application. I have domain and application services. I have created my DTOs for multiple purposes separately. But confused about which way I should use them from the API viewpoint.
I have complex objects lets say,
public class Entity{
public int Id { get; set; }
public string Name { get; set; }
public int? ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
}
public class Manufacturer{
public int Id { get; set; }
public string Text { get; set; }
}
And I have corresponding DTOs designed with composition now. It was separated before.
public class EntityBaseDto{
public string Name { get; set; }
}
public class EntityReadDto : EntityBaseDto{
public string Manufacturer { get; set; }
}
public class EntityWriteDto : EntityBaseDto{
public int? ManufacturerId { get; set; }
}
Now the question is,
I have a table which is filled with List<EntityReadDto> which is clear. Before, EntityReadDto also had the ManufacturerDto as fully included with id and text. Whenever I require to edit one of the entries from the table I was able to load the dropdown selected items or list of tags etc with the ids attached to the Manufacturer objects within ReadDtos. Now it is not possible. Since I wanted to simplify the codes I just converted them to strings that are read-only. Now I have created another endpoint to get an editable version of the record when needed. Ex: EntityWriteDto will be used to fill the form when the edit is clicked on a specific item. The manipulation will be carried on that DTO and sent with the PUT type request to edit the record.
I am not sure if this approach is ok for these cases. What is the best practice for this? I have many objects related to the entities from other tables. Is it ok to make a call to get an editable version from the backend or need to have it right away in a VUEjs app?
Fluent Nhibernate Many to Many association to multiple classes
We use Nhibernate and up to now we have been able use the auto mapping. But I think this is about to change.
We have a Code class that has a many to many relation with several other classes.
I’m thinking something along these lines:
public class Code
{
public virtual Guid Id { get; set; }
public virtual ICollection<CodeUsage> Usage { get; set; }
}
class CodeUsage
{
public virtual Guid Id { get; set; }
public virtual Code Code { get; set; }
// Class, [Property,] Id for "ANY" mapping to A & B
}
class A
{
public virtual Guid Id { get; set; }
public virtual ICollection<CodeUsage> Codes { get; set; }
}
class B
{
public virtual Guid Id { get; set; }
public virtual ICollection<CodeUsage> Codes { get; set; }
}
Many to Many will lead to the creation of a linking table, in the linking table their needs come a mapping to the classes using codes. In the documentation it is referred to as a “Any” mapping.
But I have no idea how get fluent to create one.
Thoughts anyone? or even better: a solution <);o)}{
You can't map <many-to-any> in Fluent NHibernate - it's not supported.
I think it may be a good reason to move to mapping-by-code, that supports it well.
I'm having some trouble figuring out the appropriate FluentNHibernate mapping syntax for the following data model and domain objects. Here's the data model I'm working against:
And I'm trying to map the following domain objects to that model:
namespace FluentNHibernateSandbox.Entities
{
public abstract class EntityBase
{
public virtual long Id { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Attribute : EntityBase
{
public virtual string Name { get; set; }
public virtual string Label { get; set; }
public virtual string Description { get; set; }
public virtual int SortOrder { get; set; }
public virtual Group Group { get; set; }
public virtual Editor Editor { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Group : EntityBase
{
public virtual string Name { get; set; }
public virtual string Label { get; set; }
public virtual string Description { get; set; }
public virtual int SortOrder { get; set; }
public virtual IList<Attribute> Attributes { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Editor : EntityBase
{
public virtual string ViewName { get; set; }
public virtual string WorkerClassName { get; set; }
}
}
In general, what I ultimately want doesn't seem like it should be all that hard to do, but I after having tried just about every combination of mappings I can think of, I still can't seem to get it right. I just need my Attribute to have a reference to the Group that it belongs to and a reference to the Editor assigned to it, and each Group should have a collection of the Attributes that are part of it. The couple of many-to-many join tables are what seem to be giving me fits. Particularly the APPLICATION_ATTRIBUTE table. Ultimately I only want the Attributes that my application is concerned with, in this case, those with an APPLICATION_ID of 4.
Any help would be greatly appreciated. Thanks.
Really kinda surprised nobody responded to this at all, but anyway. The answer/solution for this mapping situation that we came up with, which I was trying to avoid to start with, but turned out to really be the best way to go, was to create some custom views in the database that joined together all of the application-specific data I needed, and then just mapped my application's domain objects to those views. This worked at least partially because the information I needed from these tables is going to be read-only for this application, but even if I needed to write to the tables, I'm pretty sure (though haven't verified as I didn't really have need in this case) that I could have setup my views to be writeable and that would've worked too.
Hat tip to #robconery.
I've seen this (unanswered) question asked once before, but in a different context. I'm looking to have two domain objects map to the same table, WITHOUT a discriminator. The two classes are:
public class Category
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual ReadOnlyCategory ParentCategory { get; private set; }
}
and
public class ReadOnlyCategory
{
public virtual int Id { get; private set; }
public virtual string Name { get; private set; }
public virtual ReadOnlyCategory ParentCategory { get; private set; }
}
The main difference is that all public properties of ReadOnlyCategory are read-only. My idea here is that I want all users of this class to know that they should only mess with the category they are currently 'looking' at, and not any other categories in the hierarchy. (I've left off other properties regarding the subcategories.)
Clearly, in the database, Category and ReadOnlyCategory are the same thing, and NHibernate should treat them very similarly when persisting them. There are three problems wrapped into one here:
1) How do I do the mapping?
2) When instantiating the objects, how do I control whether I instantiate Category or ReadOnlyCategory?
3) When persisting the objects, will the mapping be smart enough, or do I need to use an extensibility point here?
Any pointers on how I can get this to happen?
(Or am I crazy?)
This looks like wrong object model design to me. I don't see a good reason to introduce a new class just for authorisation reasons (whether user allowed to modify a given category object?). You may as well use one class and throw for example InvalidOperationException if an end user is not supposed to modify a category.
Which entity FluentNHibernate uses as entity
I create some entity in Domain(or BLL), such as the following:
public class Role
{
public long ID { get; protected set; }
public string Name { get; set; }
public string Description { get; set; }
public List<User> Users { get; set; }
public Role()
{
Users = new List<User>();
}
}
And I want make use of FlunetNHibernate to map them, but get errors:
The following types may not be used as proxies:
Freeflying.Domain.Core.Profile: method get_ID should be 'public/protected virtual' or 'protected internal virtual'
Yes, I recall the programmer requirement when use FluentNHibernate, the entity should be like this:
public class Role
{
public virtual long ID { get; protected set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
}
But It looks wired. Do you think so? How do you do when using FluentNHibernate? I don't want go back to Domain layer and add virtual for every property.
This is a basic requirement for using NHibernate; It allows NHibernate to generate a proxy class that descends from your class for lazy loading and such.
I have not seen a method of removing this requirement, though if such a thing is possible it would mean that you could not use lazy loading of objects and/or properties.
Here's a blog post that explains this a bit more; It also offers a way to avoid marking your properties as virtual, although I would really recommend that you do not use this method (marking classes to avoid lazy loading) as the benefits of lazy loading in most circumstances far outweigh the cost of making your properties virtual.