How to map a model with an optional parent in NOSQL - sql

I'm in a situation where I have two entities in my database which I'm trying to convert to NOSQL. Site and Customer
A Customer has Sites
A Site can belong to a Customer but doesn't need one
I started thinking I would swap it around so I have a collection of Sites that can each have a customer but doesn't require one. But I still feel that Customer should be the parent as that seems more natural. However what would I do with sites without a customer in that case.
Is there a convention out there for dealing with this situation? I admit I'm still getting used to how things work in NOSQL
Thanks in advance.

If you use an object oriented database my suggestion would be to implement classes Site, Customer and SitePerCustomer like this
[Database]
public class Site
{
...
}
[Database]
public class Customer
{
public IEnumerable<Site> ConnectedSites
{
get
{
return SQL<Site>("SELECT s.Site from SitePerCustomer s WHERE s.ConnectedCustomer=?", this);
}
}
[Database]
public class SitePerCustomer
{
public Site ConnectedSite;
public Customer ConnectedCustomer;
}
Then you can use Customer for what it is and Site as well. The Customer instances can relate to all sites using a get property or method.

Related

sql email notification for customers

I have a scenario where by I create a product on the asp.net front end and it goes into a SQL database. When creating a product I have to assign it to 3 suppliers on the font end to say that these suppliers area the only ones who supply the product.
However when I have entered the data for the product and clicked submit, the data is saved in the products table. I want it to also send an email to the assigned suppliers to say "you have been assigned to "
What is the best thing to do? I have been recommended triggers but not sure how to use them.
This is more of an architecture question than a SQL Server question, but I'm happy to give my opinion. I'm going to step back from the idea of doing it in the database and give you a different perspective on it.
What you are describing falls in the territory of business rules, and putting business rules in the database, especially in triggers, can make your application more complicated to understand and maintain.
Instead, I would recommend creating a service layer and coordinate all business rules like this in the service layer instead of mixing them into the database. That way the database has one job (a single responsibility) and that is to store the data... it doesn't need to know anything else.
Personally, I like organizing my code this way as it makes it easier to unit test and makes it easier to adhere to SOLID principles.
Please bear with me for an example... In C#, you might have a class that looks something like this:
class ProductService
{
private Database _database;
private Notifier _notifier;
public ProductService(Database database, Notifier notifier)
{
_database = database;
_notifier = notifier;
}
public void AddProduct(Product product)
{
_database.SaveProduct(product);
NotifySuppliersAboutProduct(product);
}
private void NotifySuppliersAboutProduct(Product product)
{
foreach (var supplier in product.Suppliers)
{
NotifySupplierAboutProduct(supplier, product)
}
}
private void NotifySupplierAboutProduct(Supplier supplier, Product product)
{
// TODO: Construct email to/subject/body variables here
_notifier.SendEmail(to, subject, body);
}
}
ProductService is just coordinating the work by assembling other classes it needs and calling them to accomplish something, in this case Adding a product.
Database is a class that handles all interfacing with the database.
Notifier is a class that handles all email sending.
I hope this idea helps or at least gives you another option to consider. Good luck!

ValueObject Persistence in NHibernate / Fluent NHibernate

I'm a total newbie with ORMs and the DDD, so please, be patient with me. Also, I'm no native speaker so the domain lingo will be a little hard to express in English.
I'm developing a system to control lawsuits.
My domain has an Entity called Case.
Public class Case
{
public virtual int Id { get; set; }
public virtual List<Clients> Clients { get; set;}
public virtual LawsuitType LawsuitType { get; set;}
}
The CaseType is, from what I gathered, a Value Object. It's a simple type, it has only the case type description. Example: "Divorce", "Child Support", etc. It is only the description that interests me. But I don't want to be a free descriptor. I want to control the options presented to the user, and also do some reports.
So I was thinking to map this on Database with the table "LawsuitTypes". The table would have a int Id, and a string descriptor.
Can I accomplish that using ComponentMap? Or have I got things wrong and the CaseType is an Entity?
Thanks, Luiz Angelo.
Edit:
Using an enum was suggested. But that wouldn't work because it would mean that the LawsuitTypes are set by the developer, and not the user. Some users have the power to add/remove LawsuitTypes, while others don't.
IMHO you should treat LawsuitTypes as an own entity. Keep in mind, that you may want to extend the LawsuitTypes with additional information some day (requirements changes very fast sometimes). What comes in my mind is a "default" property or somethig like that... This means additional work of cource, but this way you are more flexible for future needs.
If I understand your question correctly, the Description("") attribute and a simple enum should work. More on that here.
public enum LawsuitTypes
{
Divorce,
[Description("Child Support")]
ChildSupport,
[Description("Some Other Element")]
SomeOtherElement
}

Filter contents of lazy-loaded collection with NHibernate

I have a domain model that includes something like this:
public class Customer : EntityBase<Customer>, IAggregateRoot
{
public IList<Comment> Comments { get; set; }
}
public class Comment : EntityBase<Comment>
{
public User CreatedBy { get; set; }
public bool Private { get; set; }
}
I have a service layer through which I retrieve these entities, and among the arguments passed to that service layer is who the requesting user is.
What I'd like to do is be able to construct a DetachedCriteria in the service layer that would limit the Comment items returned for a given customer so the user isn't shown any comments that don't belong to them and are marked private.
I tried doing something like this:
criteria.CreateCriteria("Comments")
.Add(Restrictions.Or(Restrictions.Eq("Private", false),
Restrictions.And(Restrictions.Eq("Private", true),
Restrictions.Eq("CreatedBy.Id", requestingUser.Id))));
But this doesn't flow through to the lazy-loaded comments.
I'd prefer not to use a filter because that would require either interacting with the session (which isn't currently exposed to the service layer) or forcing my repository to know about user context (which seems like too much logic in what should be a dumb layer). The filter is a dirty solution for other reasons, too -- the logic that determines what is visible and what isn't is more detailed than just a private flag.
I don't want to use LINQ in the service layer to filter the collection because doing so would blow the whole lazy loading benefit in a really bad way. Lists of customers where the comments aren't relevant would cause a storm of database calls that would be very slow. I'd rather not use LINQ in my presentation layer (an MVC app) because it seems like the wrong place for it.
Any ideas whether this is possible using the DetachedCriteria? Any other ways to accomplish this?
Having the entity itself expose a different set of values for a collection property based on some external value does not seem correct to me.
This would be better handled, either as a call to your repository service directly, or via the entity itself, by creating a method to do this specifically.
To fit in best with your current model though, I would have the call that you currently make to get the the entities return a viewmodel rather than just the entities;
public class PostForUser
{
public Post Post {get; set;}
public User User {get; set;}
public IList<Comment> Comments}
}
And then in your service method (I am making some guesses here)
public PostForUser GetPost(int postId, User requestingUser){
...
}
You would then create and populate the PostForUser view model in the most efficient way, perhaps by the detached criteria, or by a single query and a DistinctRootEntity Transformer (you can leave the actual comments property to lazy load, as you probably won't use it)

Where to expose the results of a specific SQL query in the domain model

Which of these examples would be the best way to expose a collection of Orders for a specific Person that contain a specific Product and why? Or maybe there is a better way to do this alltogether? (Sorry I am new to domain modeling). The Orders list is pulled from the database with an SQL query and turned into a List collection.
A Person has 1 to many Orders and an Order has 1 to many Products.
1)
class Person
{
List OrdersContaining(Product p)
{.....}
}
2)
class Order
{
List ForPersonContainingProduct(Person person, Product product)
{.....}
}
2)
class Product
{
List OrdersFor(Person p)
{.....}
}
I would not expose such a method directly on the domain object itself, which encapsulates the data. Rather, I would use the DAO pattern applied to the Order domain. Which, in essence, is a variation of your #2:
class OrderDAO {
List<Order> listByPersonAndProduct(Person person, Product product){
.....
}
}
This way, the various patterns of access that you need to add over time are separated from the Order domain object.
Person could still have a .Orders collection which has all their orders. Then it becomes a question of lazy loading an populating this collection when you know you're going to need it. Something like N/Hibernate helps a lot here.

Fluent NHibernate Architecture Question

I have a question that I may be over thinking at this point but here goes...
I have 2 classes Users and Groups. Users and groups have a many to many relationship and I was thinking that the join table group_users I wanted to have an IsAuthorized property (because some groups are private -- users will need authorization).
Would you recommend creating a class for the join table as well as the User and Groups table? Currently my classes look like this.
public class Groups
{
public Groups()
{
members = new List<Person>();
}
...
public virtual IList<Person> members { get; set; }
}
public class User
{
public User()
{
groups = new Groups()
}
...
public virtual IList<Groups> groups{ get; set; }
}
My mapping is like the following in both classes (I'm only showing the one in the users mapping but they are very similar):
HasManyToMany<Groups>(x => x.Groups)
.WithTableName("GroupMembers")
.WithParentKeyColumn("UserID")
.WithChildKeyColumn("GroupID")
.Cascade.SaveUpdate();
Should I write a class for the join table that looks like this?
public class GroupMembers
{
public virtual string GroupID { get; set; }
public virtual string PersonID { get; set; }
public virtual bool WaitingForAccept { get; set; }
}
I would really like to be able to adjust the group membership status and I guess I'm trying to think of the best way to go about this.
I generally only like to create classes that represent actual business entities. In this case I don't think 'groupmembers' represents anything of value in your code. To me the ORM should map the database to your business objects. This means that your classes don't have to exactly mirror the database layout.
Also I suspect that by implementing GroupMembers, you will end up with some nasty collections in both your user and group classes. I.E. the group class will have the list of users and also a list of groupmembers which references a user and vice versa for the user class. To me this isn't that clean and will make it harder to maintain and propagate changes to the tables.
I would suggest keeping the join table in the database as you have suggested, and add a List of groups called waitingtoaccept in users and (if it makes sense too) add List of users called waitingtoaccept in groups.
These would then pull their values from your join-table in the database based on the waitingtoaccept flag.
Yes, sure you need another class like UserGroupBridge. Another good side-effect is that you can modify user membership and group members without loading potentially heavy User/Group objects to NHibernate session.
Cheers.