nHibernate Criteria query with missing mapping - nhibernate

I'm trying to do the following thing:
ICriteria criteriaSelect =
session
.CreateCriteria(typeof(Employees))
.CreateCriteria("Orders")
;
var test = criteriaSelect.List<Orders>();
With:
public class Orders{
public virtual int OrderID { get; private set;}
}
public class Employees{
public virtual int EmployeeID { get; private set;}
public virtual IList<Orders> Orders { get; private set; }
}
And I get the error: "No persister for: Employees".
Please note that for decoupling reason, I don't want Orders to
reference Employees.
Thanks for your help,
Stephane

The Criteria API is for indicating the specification you want during the query. You will need to establish mappings for your entities using either the older hbm.xml files or using Fluent NHibernate. See chapter 5 on Basic O/R Mapping for more details.

Related

Designing a hierarchy of abstract classes and using it in EF Core

I am using .NET Core with Entity Framework Core to build a finance app and I want to know how to make my design better.
I have a 1 to Many relationship between two entities, BankAccount and Transaction. In a way that:
1 Account can have many Transactions
1 Transaction Belongs to 1 Account
However, I want to include bank accounts and transactions coming from different 3P sources. And while this relationship and the main fields are common across different sources, each source has a unique set of properties I want to keep.
To achieve this I decided to define these entities as abstract classes. This way, you can only instantiate concrete versions of these entities, each coming from a particular data source.
public abstract class Transaction : BaseEntity
{
public DataSource Source { get; private set; }
public decimal Amount { get; private set; }
public DateTime Date { get; private set; }
public string Name { get; private set; }
public BankAccount BankAccount { get; private set; }
public Guid BankAccountId { get; private set; }
...
}
public abstract class BankAccount : BaseEntity
{
public DataSource Source { get; private set; }
public string Name { get; private set; }
public Balance Balance { get; private set; }
public IEnumerable<Transaction> Transactions {get; private set;}
...
}
Here is a trimmed down example of the concrete implementations:
public class PlaidTransaction : Transaction
{
public string PlaidId { get; private set; }
private PlaidTransaction() : base() { }
public PlaidTransaction(decimal amount, DateTime date, string name, Guid bankAccountId, string plaidId) : base( amount, date, name, bankAccountId)
{
PlaidId = plaidId;
}
}
public class PlaidBankAccount : BankAccount
{
public string PlaidId { get; private set; }
...
}
I am using .Net Core with Entity Framework Core to persist my data and I managed to store my concrete classes all in the same table (TPH approach)
This works great and now all my entities live under the same table. So I can either query all Transactions or those of a certain type using LINQ's OfType<T> extension.
DbSet<Transaction> entities = _context.Set<Transaction>();
IEnumerable<PlaidTransaction> plaidTransactions = entities.OfType<PlaidTransaction>();
However, when I access my BankAccount field from my concrete Transaction I don't get the concrete instance. So something like this doesn't work.
plaidTransactions.Where((t) => t.BankAccount.PlaidId)
Instead I have to cast it:
plaidTransactions.Where((t) => (t.BankAccount as PlaidBankAccount).PlaidId)
What can I do to avoid casting everywhere? I feel there's a missing piece in my design that would make all my code easier. I was thinking of overriding the getters on my concrete classes but I don't know if I can return a derived class to a base class method. Maybe I should move to generics but 1) I still want to keep the fixed relationship between these entities and 2) how would EF Core handle this?

ASP.NET MVC 4 getting error "Exception has been thrown by the target of an invocation"

I'm Using Composite keys in below Model class of mvc and same thing.I did in MS SQL Server database having two columns with both are PK,FK but i am getting error in InitializeSimpleMembershipAttribute class like "Exception has been thrown by the target of an invocation" please help me to get how to create.
This is my model class
[Table("webpages_UsersInRoles")]
public partial class UsersInRoles
{
[Column(Order = 0)]
public int RoleId { get; set; }
public virtual NewRoles roles { get; set; }
[Column(Order = 1)]
public int UserId { get; set; }
public virtual UserProfile UserProfiles { get; set; }
}
why you doing that? you dont need to define this yourself. if you use AccountController and if you use WebSecurity Role this table is created for you in SimpleMemberShipInitializer filter. and you just need to use the built in functionality provided for you with SimpleMembership provider.
in short, you dont need to define this table which IMO is the reason you having these problems.

Fluent Nhibernate Cascade.None() results in HasOne foreign key relationship not being persisted

I'm having issues with Nhibernate persisting a HasOne Relationship for one of my entities with Cascade.None() in effect. My domain model involves 4 classes listed below.
public class Project
{
public virtual int Id {get;set;}
public virtual IList<ProjectRole> Team { get; protected set; }
}
public class ProjectRole
{
public virtual int Id { get; set; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
}
public class Role
{
public virtual int Id { get; set; }
public virtual string Value { get; set; }
}
public class User
{
public virtual int Id { get; protected set; }
public virtual string LoginName { get; set; }
}
So basically we have projects, which have a list of ProjectRoles available from the Team property. Each ProjectRole links a User to the specific Role they play on that project.
I'm trying to setup the following cascade relationships for these entities.
project.HasMany<ProjectRoles>(p=> p.Team).Cascade.All()
projectRole.HasOne<Role>(r => r.Role).Cascade.None()
projectRole.HasOne<User>(r => r.User).Cascade.SaveUpdate()
I've used fluent nhibernate overrides to setup the cascades as above, but I'm finding that the line
projectRole.HasOne<Role>(r => r.Role).Cascade.None()
is resulting in the ProjectRole.Role property not being saved to the database. I've diagnosed this be looking at the SQL Generated by Nhibernate and I can see that the "Role_id" column in the ProjectRoles table is never set on update or insert.
I've also tried using
projectRole.HasOne<Role>(r => r.Role).Cascade.SaveUpdate()
but that fails as well. Unfortunately leaving it Cascade.All() is not an option as that results in the system deleting the Role objects when I try to delete a project role.
Any idea how to setup Cascade.None() for the ProjectRole-> Role relationship with out breaking persistence.
HasOne is for a one-to-one relationship which are rare. You want to use References to declare the one side of a one-to-many relationship. Making some assumptions about your domain model, the mapping should look like:
project.HasMany<ProjectRoles>(p=> p.Team).Inverse().Cascade.AllDeleteOrphan()
projectRole.References<Role>(r => r.Role);
projectRole.References<User>(r => r.User);
See also this question about the difference between HasOne and References.

Fluent NHibernate - Map 2 Identical classes to same table

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.

Mapping a derived class with additional collection property in nhibernate

I'm trying to use the table-per-subclass (which fluent-nhibernate automaps by default) with a class structure like the following:
public class Product
{
public virtual int Id{ get; set; }
public virtual string Title{ get; set; }
}
public class ProductPackage : Product
{
public ProductPackage(){ Includes = new List<Product>(); }
public virtual IList<Prodcut> Includes{ get; private set; }
[EditorBrowsable( EditorBrowsableState.Never )]
public class ProductPackageAutoOverride : IAutoMappingOverride<ProductPackage>
{
public void Override( AutoMap<ProductPackage> mapping )
{
mapping.HasManyToMany( x => x.Includes )
.WithTableName( "IncludesXProduct" )
.WithParentKeyColumn( "ProductId" )
.WithChildKeyColumn( "IncludesProductId" )
.Cascade.SaveUpdate();
}
}
}
Instead of adding a new table "IncludesXProduct" to represent the many-to-many mapping, it adds a property "ProductPackageId" to the Product table. Of course persisting to this schema doesn't work.
Have I missed something simple or is this type of thing not really supported by NHibernate?
It is possible to do this with NHibernate. Unfortunately my fluent syntax isn't very good, but it looks like FNH is somehow regarding the relationship as a many-to-one rather than a many-to-many.
If you tag your question with "fluent-nhibernate" then you may get more knowledgeable people answering.