Disable possibility to update subclasses - c#

I am developing a inheritance strategy in fluent nhibernate. Everything works correctly but I have a one question. Is there any possibility to disable updating base property through the subclass?
Here is a dummy code:
public class ObjectA
{
public virtual string StatusA { get; set; }
}
public class ObjectB : ObjectA
{
public virtual string StatusB { get; set; }
}
public class ObjectBMap : SubclassMap<ObjectB>
{
public ObjectBMap()
{
Map(x => x.StatusB);
}
}
When I am updating objectB I don't want to update StatusA. I want to change the status A when I will be updating ObjectA. Does nhibernate have this kind of feature? Does it have sense?
Edit: Additional explenation
The reason why I want to do such thing is that in my system (asp mvc application) we have two different places where we manage objectsA and objectsB. First we create object A and later we want to 'convert' object A to objectB. Then we can edit these two objects in two different modules.
My flow for editing objectB:
-Read objectB from db, convert it to viewmodel
-post form from view, convert view data from form to objectB and update in db.
I don't want to extend view model for objectB for data from object A, store this data in some hidden fields and convert from view model.
I thought that if could mark that this data couldn't be updated by Session.SaveorUpdate(objectB) it would resolve my problems. So basically that was my question.

Try to check the documentation:
5.1.3. class
Small cite:
<class
name="ClassName" (1)
table="tableName" (2)
...
dynamic-update="true|false" (7)
dynamic-insert="true|false" (8)
...
...
(7) dynamic-update (optional, defaults to false): Specifies that UPDATE SQL should be generated at runtime and contain only those columns whose values have changed.
(8) dynamic-insert (optional, defaults to false): Specifies that INSERT SQL should be generated at runtime and contain only the columns whose values are not null.
What we can see, is the setting "dynamic-update" ... which does what we would expect: update only properties which were changed
This would be the most native way how to learn NHibernate to issue updates only to the ObjectB ... if there are no changes in the ObjectA defined properties.
But in general: simply leave it up NHibernate. What it does, would most likely be the best we should require... it is a mature tool
EXTEND
Based on the question extension - I would say: do not go that way... Do not.
With ORM tools you will gain a lot, if your model, the business domain model, is kept as easy as it could be. NHibernate can help with lot of stuff e.g.:
selection of all or only some properties - called projections
paging
sorting
filtering
cascading of WRITE operations
and even more...
But it won't help you to manage the "unexpected" or "exceptional" domain model designs.
Please read this:
Composition over inheritance
Composition over inheritance (or Composite Reuse Principle) in object-oriented programming is a technique by which classes may achieve polymorphic behavior and code reuse by containing other classes that implement the desired functionality instead of through inheritance...

Related

Orchard model inheritance with Table-Per-Concrete-Type?

I know that the underlying ORM used in Orchard is NHibernate and it does support the so-called ClassMapping which may help customize the mappings the way we want.
However I'm not sure about how Orchard utilizes the mapping methods supported by NHibernate. In this case it seems to always use the strategy similar to Table Per Type in EF as well as some other ORMs. With that strategy, the base class will be mapped to some common table whereas the derived class will be mapped to another table which contains all properties of its own (not declared in the base class). Those 2 tables will have a one-one relationship.
Now I really want to make it use the strategy similar to Table Per Concrete Type in which the base and derived classes will be mapped to 2 different tables with all properties (including inherited properties) being mapped to columns. Those 2 tables will not have any relationship, so querying for columns in just one table will not unexpectedly generate an inner JOIN (for one-one relationship).
Actually that requirement makes sense in case we just need to partition our data (from 1 big table to 2 or more small tables that have the same schema). We don't want to re-declare or use some kind of duplicate model classes (with different names), instead we just need to create a new model class and let it inherit from one base model class containing all necessary properties.
With the current code like this:
public class ARecord {
//properties ...
}
public class BRecord : ARecord {
//empty here
}
Currently we cannot use BRecord because it is understood as another part of the ARecord, the auto-generated query (always with INNER JOIN) will be failed because of some does-not-exist table or column names.
How can I solve this?
You're not going to like it ;) In a nutshell, the answer is don't do inheritance at all. Orchard was very deliberately designed around the idea of composition, steering well clear of inheritance in its content models. Maybe the central idea in Orchard is to make the concept of content part the "atom of content", and to design those basic units as very simple and composable pieces of functionality that do one thing well.
After all these years, the concept has held remarkably well, and I've yet to see an example of a content model where inheritance would have been more elegant and appropriate. This is reflected in the way nHibernate is customized and used in Orchard, as you've discovered.
So the solution to your problem can likely be one of two things:
You're modeling contents, and you should re-think your approach towards composition of parts. If you give a little more details about your specific scenario (maybe in a new question), I'm happy to help specifically in this direction.
You're modeling non-content data, in which case you might want to consider opting out of Orchard's specific nHibernate content-specialized idiosyncrasies and do things closer to the metal. Again, if you give more specifics about your scenario, I'm happy to take a look and give some pointers.

Entity Framework 6 Code First - Comments on a Tree Structure

I'm attempting to implement heterogeneous association in my Data Model (Entity Framework 6, Code-First approach).
I have an existing structure of classes, let us call them Tree, Branch and Leaf. A Tree may have many Branch objects, and a Branch may hold many Leaf objects. The relationships between the three levels have a cascade-delete behavior (delete a branch and you also delete the leaves, etc.).
Now I'm trying to let users add a comment-like object on each of those levels. I had a few problems related to data-modelling, as I want each of the 3 entity types to be able to have many comments and each comment to belong to one and only one entry. I'd also like for all comments to be in the same table. I've tried two different approaches:
Alt. 1
Implement inheritance so that the Comment (abstract) can be a TreeComment, BranchComment or LeafComment, following the Table per Hierarchy (TPH) approach (as seen, for example, here) of having an abstract class (Comment) for comments and then derive it to TreeComment, BranchComment, etc. That is achieved by coding the models like this:
public abstract class Comment
{
// ID
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ID { get; set; }
}
public class TreeComment: Comment
{
// Foreign Keys
public Guid TreeID { get; set; }
// Navigation Properties
public virtual Tree Tree { get; set; }
}
(... BranchComment and LeafComment ...)
(... add virtual ICollection<TreeComment> to Tree, virtual ICollection<BranchComment> to Branch, etc.)
...which can be expressed with this diagram:
The problem with this approach is that the relationship between the Comment table and the other 3 doesn't have ON DELETE CASCADE or ON DELETE SET NULL set. If I try to change that to more than one table, I get a:
Introducing FOREIGN KEY constraint 'FK_Comment_Branch_BranchID' on
table 'Comment' may cause cycles or multiple cascade paths. Specify ON
DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY
constraints.
I understand that this is because SQL Server "doesn't know" that only one of the FK's in the Comment table is supposed to be used at any time.
Alt. 2
Generalize the Tree/Branch/Leaf trio into a CommentableEntity using the Table per Type (TPT) approach and connect the Comment table to that abstract one. This can be achieved by implementing inheritance in the model classes (just like I did before) and adding the annotations [Table("Tree")], [Table("Branch")] and [Table("Leaf")] to each of the subclasses to make sure we get a table for each (and not a single table like in TPH). The Model, then looks like this:
This approach has two problems:
Deleting a concrete object (e.g. a branch) will not delete the base entry in the abstract table, leaving "garbage" (abstract entities and their comments) behind.
The FK relationship between the abstract and concrete classes lacks a cascade delete. So I can't really delete the base object. If I try to add one I get another complaint on how introducing such rule would cause cycles of multiple cascade paths.
I've also tried using DB triggers (CREATE TRIGGER ... INSTEAD OF DELETE...) on both approaches but they seem to be a big no-no as EF can't track the changes done by them.
This is frustrating and I'm sure this (comments on a tree structure) is a very typical scenario in Web development; but I can't seem to find a way to allow it. I'm looking for all advice I can get on how to effectively model these relationships (EF 6 Code First) without placing too much weight on the Business Logic layer.
EDIT:
I believe this is what user #Deepak Sharma mentioned in his comment: TPH inheritance in the node classes. If so, this also doesn't work for the same reason: cycles of multiple cascade paths.
Ok, so here's how I'm currently solving the problem:
I chose the second alternative - generalize the Tree/Branch/Leaf trio (let's call these "nodes" for simplification) into a CommentableEntity (the base class) using the TPT approach - as seen above. I end up with one table for each of the three node classes + one base class that holds the relationship to a Comment table.
Then, in my InitializeDatabase(MuDbContext context), I added one Stored Procedure and Trigger for each of the three tables to the database using the context.Database.ExecuteSqlCommand() method.
1) The Stored Procedure has to be mapped in EF like this:
this.MapToStoredProcedures(s => s.Delete(d => d.HasName("TriggerName").Parameter(b => b.ID, "parameter_name")));
... for each of the three models and basically is a replacement for the default delete. In my case, I wrote it so that first it deletes the actual node in its table (Tree/Branch/Leaf) and then the corresponding base object (CommentableEntity).
2) The Trigger fires after a node is deleted and makes sure that the corresponding base object is also deleted.
In case you're wondering why do I have such redundancy (a Trigger and a Stored Proc. that do almost the same thing) it's because whenever a node is deleted (say, a tree), EF calls its Stored Proc. in order to delete it. Then, the nested nodes (the tree's branches) are deleted via the DB's cascade-delete, which doesn't delete the base objects, and not via the Stored Proc.. Thus, the Trigger. On the other hand, if I only had the trigger (no Stored Proc.), EF would freak out after the deletion because it wouldn't be able to track its changes.
I could, of course, just change each of the Stored Proc. for each of the tables so that they also delete all of the nested objects as well and remove the cascade-delete setting. But the current solution seems to be working and good enough for me.
I will test this out and delete this answer if I find out that this doesn't actually work. If you see any disadvantages in this approach (and know how to avoid them) please leave a comment.
Possibly the answer is to augment Alt 1 by declaring some rules within the OnModelCreating Method. Also this assumes that the the Tree, Branch and Leaf classes have a Comments collection against them.
Within your DbContext you could do the following ...
public class YourDbContext : DbContext
{
... your DbSet properties
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Tree>()
.HasMany<TreeComment>(o => o.Comments)
.WithRequired(com => com.Tree)
.HasForeignKey(com => ds.TreeID)
.WillCascadeOnDelete(false);
}
}

Map Multiple Tables to One Table Produces Foreign Key Column for each in Fluent NHibernate

I want to Point 3 tables Property, Business, Automobile to single Table named Utility.
Using Fluent NHibernate, I followed
public UtilityMap()
{
// some Mappings
References<Automobile>(x => x.Automobile, "LeaseRefId").Cascade.None();
References<Business>(x => x.Business, "LeaseRefId").Cascade.None();
References<Property>(x => x.Property, "LeaseRefId").Cascade.None();
}
and in Each table that maps to the Utility, I followed
public AutomobileMap()
{
//Some Mappings
HasOne<Utility>(x => x.CommonDatas)
.Cascade.All();
}
"I want to have a single column in Utility Table that can store the
references of all the three (Automobile, Business, Property) tables.
But fluent Nhibernate is creating foreing key columns for each of the
table referenced. I want to avoid this."
Is there any way to achieve this??
Please suggest
Thanks in Advance.
For this to work as you expect, you'll need to have a base class for Automobile, Business and Property classes. Let's call it LeaseSubject. Presumably, you already have something like that in your domain model.
Your Utility class should have only one property, instead of three you have now:
public virtual LeaseSubject LeaseSubject { get; set; }
This way you not only have easier mapping, but also promote the maintainability of your code. What if at some later time you decide to have one more lease subject, i.e. Yacht? Instead of adding another Yacht property to your Utility class, you just need to inherit from LeaseSubject, and it could be contained within the LeaseSubject property on Utility class.
Now you could map your Utility simply as:
public UtilityMap()
{
// Other mappings...
References(x => x.LeaseSubject, "LeaseRefId");
}
For mapping Automobile, Business and Property classes, you would use one of three available NHibernate inheritance strategies:
table per class hierarchy
table per subclass
table per concrete class
For FluentNHibernate inheritance mapping, take a look here.
Since you already have separate tables, I believe the correct strategy for your case would be Table per concrete class. You can find some more info in this article.

How to use Entity Framework in Enterprise application

i have some questions of how to use the Entity Framework in an enterprise application.
First of all, i work with ADO.NET for many years now and i use objects to reflect the data that i get from the database provider.
Every time i want to change something or insert something into the database.
I just call a Save() method and get the job done.
Every object has a DatabaseManager that manage the queries to the DataAccess layer.
For example
public class Article{
public int ID{get;set;}
public string Title{get;set;}
.....
public bool Save(){
if(this.ID == -1){
return new ArticleDatabaseManager().InsertArticle(this);
}else{
return new ArticleDatabaseManager().UpdateArticle(this);
}
}
}
public ArticleDatabaseManager : DatabaseManager
{
...ADO.NET code
}
I don't know if i have to use the same architectur or change all the way i use this objects in my application.
I thought if i create something like the above i can do something like this :
public class Article{
public int ID{get;set;}
public string Title{get;set;}
.....
public bool Save(){
if(this.ID == -1){
return new ArticleDatabaseManager().InsertArticle(this);
}else{
return new ArticleDatabaseManager().UpdateArticle(this);
}
}
}
In the Each DatabaseManager implements some Link To Entities or even EntitySQL to do the same job like the old DatabaseManager does.
Fill the Business models with the values that i from the Entity Objects.
Then i could work with the Business as before and just any time i want to do some changes i communicate via EntityFramework to the Database.
Sould i implement something like the above?
Sould i just inherit the previous business objects to the entity objects?
EX :
public class Article : ArticleEntity
{
//some properties for validation etc
}
Sould i use something completely different?
I Just Don't knwo:/
I have no experience with other ORM. Just mine hand written "ORM" System.
Thank you very much.
I'm sorry for my lack of English and i know that i ask too much in a single question...
But moving from one technology to an other for a dinosaur like me is like i change Country:/
Did you at least try to use some EF tutorial? If not it is time to do that because we cannot explain you everything about EF in single answer (even in multiple - that is not purpose of SO to replace tutorials and learning materials). That should give you pretty clear answer about all your stuff related to your database managers.
In general what you did till know is very close to Active record pattern. If your objects also has static methods used to retrieve object from database it is Active record pattern. When using EF you usually don't use this pattern and you don't need any database manager. EF is build around class which is called context and this context works as your database manager for all entities you are using. It is possible to add saving and retrieval methods to entities but because it breaks separation of concerns and it makes your entities heavily dependent on EF and persistence (trend is to make them completely independent = POCO) it is usually not used.
Don't derive any custom class from entity. EF will not be able to use your derived type. Use entity mapped in EF as your class and add all custom properties and methods directly to this class (you can even create that class from scratch if you don't want to use code generators). In case of generated entities you can add custom code in partial classes. If you don't use EF entity as your object you will have to manually handle conversion from one to other (or use some tool like AutoMapper).
EF is not able to work with XML column - it will handle it as string. Especially if you plan to use these data for some ordering or filtering and if they have fixed structure you should model them as separate tables / entities. If it is really just structured content (with dynamic structure) you can use it as XML string.

how does your custom class relate to the database

Okay, so i've studied c# and asp.net long enough and would like to know how all these custom classes i created relate to the database. for example.
i have a class call Employee
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}
and i have a database with the following 4 fields:
ID
Name
EmailAddress
PhoneNumber
it seems like the custom class is my database. and in asp.net i can simple run the LINQ to SQL command on my database and get the whole schema of my class without typing out a custom class with getter and setter.
so let's just say that now i am running a query to retrieve a list of employees. I would like to know how does my application map to my Employee class to my database?
by itself, it doesn't. But add any ORM or similar, and you start to get closer. for example, LINQ-to-SQL (which I mention because it is easy to get working with Visual Studio), you typically get (given to you by the tooling) a custom "data context" class, which you use as:
using(var ctx = new MyDatabase()) {
foreach(var emp in ctx.Employees) {
....
}
}
This is generating TSQL and mapping the data to objects automatically. By default the tooling creates a separate Employee class, but you can tweak this via partial classes. This also supports inserts, data changes and deletion.
There are also tools that allow re-use of your existing domain objects; either approach can be successful - each has advantages and disadvantages.
If you only want to read data, then it is even easier; a micro-ORM such as dapper-dot-net allows you to use our type with TSQL that you write, with it handling the tedious materialisation code.
Your question is a little vague, imo. But what you are referring to is the Model of the MVC (Model-View-Controller) architecture.
What the Model , your Employee Class, manages data of the application. So it can not only get and set (save / update) your data, but it can also be used to notify of a data change. (Usually to the view).
You mentioned you where using SQL, so more then likely you could create and save an entire employee record by sending an Associative Array of the table data to save it to the database. Your setting for the Class would handle the unique SQL syntax to INSERT the data. In larger MVC Frameworks. The Model of your application inherits several other classes to handle the proper saving to different types of backends other than MS SQL.
Models will also, normally, have functions to handle finding records and updating records. This is normally by specify a search field, and it returning the record, of which would include the ID and you would normally base this back into a save / update function to make changes to record. You could also tie into this level of the Model to create revision of the data you are saving
So how the model directly correlates to your SQL structure is dependent on how you right it. Or which Framework you decide to use. I believe a common one for asp.net is the Microsoft's ASP.Net MVC
Your class cannot be directly mapped to the database without ORM tool, The ORM tool will read your configuration and will map your class to DB row as per your mappings automatically. That means you don't need to read the row and set the class fields explicitly but you have to provide mapping files and have to go through the ORM framework to load the entities, and the framework will take care of the rest
You can check nHibernate and here is getting started on nHibernate.

Categories

Resources