nhibernate entity multi mappings - c#

I have entity fluently mapped to existing oracle view:
public class MyEntityMap : ClassMap<MyEntity>
{
public class MyEntityMap()
{
ReadOnly();
SchemaAction.None();
//mappings
}
}
I'm querying oracle view for entities and filtering them based on certain criteria, let's say, where created_date more than 14 days. Those entities should be written into the database for future reporting use. For that purpose I've created a table which is exact clone of oracle view in terms of fields. And I'd like to map exactly the same MyEntity to my own table. Something like that:
public class MyHistoricalEntityMap : ClassMap<MyEntity>
{
public class MyHistoricalEntityMap()
{
Table("HistoricalEntities");
//mappings
}
}
Also, I have a service responsible for querying view, but I want to add a method to store my historical entities, smth like below:
public class MyEntityService : IMyEntityService
{
private IRepository<MyEntity> _repository;
...
public IEnumerable<MyEntity> GetEntities(){...}
public void StoreHistoricalEntities(IEnumerable<MyEntity> historicalEntities) {...}
}
So, question is: how do I specify, that I want to (or nhibernate should) use MyEntityMap for querying, but MyHistoricalEntityMap for storing results? Or what other solution can I apply?
Thanks,

You can't use two different mappings for an entity.
What you can do is use custom SQL for loading.

Related

Multiple Tables With Same Structure Entity Framework

We have a database with multiple tables with Same structure
Table 1
Key ID ........
Table 2
Key ID .......
The number of tables can be dynamic based on configuration.
I am trying to upgrade the data access Layer to Entity framework. I have created one class representing the structure of the table. My Plan is to use the same class for all the tables with same structure. Bubt I could not find enough information on how to do this. What I understood is that I can map one class to one table only.
Is there any way to achieve this using entity framework?
The easy way: have an abstract base class with all the properties, and map concrete types:
public abstract class BaseClass
{
public int Id { get; set; }
public string StringField { get; set; }
/* Other fields */
}
[Table("Table1")]
public class Table1 : BaseClass
{
}
[Table("Table2")]
public class Table2 : BaseClass
{
}
I'm not answering whether that design is good or bad (I wouldn't say I like it as you explained it), I'm just answering the question
And now for a completely different approach which I have used successfully in EF Core:
Create a parameterized stored procedure which uses some dynamic SQL to return the actual table you want and use the FromSql feature.

Customizing features in Repository design classes

I could be probably wrong in the manner I am thinking the things will work
but I am really confused as I am using repository design pattern for the first time.
The problem is that the repository class will only have
GetaLL(), GetALLByID(), Update() or Save().
But what If I need to extract the records such that I have groupofUsers in one table
and for that each group I need to count how many users are there in each group. The user table is a different table.
The relation can be assumed as "UserGroup" as parent table which have unique
usergroups but this UserGroup table has a key which will be foreign key in
another table "Users". There could be many users in a group and similary with this
I need to find out how many roles are under the same table i.e "UserGroup".
This is another table "roles" which will have "UserGroups" in the same way as
it wasin "users" table.
And here is how I ahve to get the records. My repository only have
public abstract class Repository<T>
where T : class
{
private readonly IDbSet<T> _dbset;
public virtual IQueryable<T> GetAll()
{
return this._dbset;
}
}
And in controller I am calling it as below:
private readonly Repository<UserGroup> _GroupRepository;
public IEnumerable<UserGroupModel> GetListedGroups()
{
var list = this._GroupRepository.GetAll();
}
You can have a new class which derived from Repository<T> and add new methods in it.
public class UserGroupRepository : Repository<UserGroup>
{
public UserCountInGroups GetUserCountInGroup()
{
// Do something with this._dbset here.
}
}
So in the controller you use UserGroupRepository instead of Repository<UserGroup>
private readonly UserGroupRepository _GroupRepository;
public IEnumerable<UserGroupModel> GetListedGroups()
{
var list = this._GroupRepository.GetAll();
var userCount = this._GroupRepository.GetUserCountInGroup();
// Do something here.
}

Can Entity Framework automatically extend models with datetime fields to keep the changing date

Can you tell Entity Framework to add an extra field for each field of a certain type? For example: Is it possible to generate a ChangedAt datetime field for each boolean field defined in the model, so this
public bool Confirmed { get; set; }
could result in a table with an additional field ConfirmedChangedAt where the value is updated each time the boolean value is changed.
Usually behavior like this should be implemented directly into your business logic and not automatically into the data layer. So I suggest to write something like this:
// entity
public class Order
{
public bool Confirmed { get; set; }
public DateTime? ConfirmedAt { get; set; }
}
// business logic
public class OrderManager
{
.................
public void Confirm( Order order )
{
// changing of entity status
order.Confirmed = true;
order.ConfirmedAt = DateTime.Now;
// storing new entity status
_orderRepository.Update( order );
................
}
}
I think if i understand you correctly, You are expecting the Entity Framework to be able to add columns to the database automatically so that you don't have to add them manually, Well you have 2 cases:
if you are using the database first approach you could achieve this
by using a query that's specific to your needs to add these columns
for you based on the conditions you have.
If you are using the code first approach and you have an existing database you may reverse engineer the database using the Entity Framework Power Tools and you could customize the T4 Templates to generate the entities with the extra properties that you need.
Plain answer no.
But it's depend on way how you interact with EF (code first, model first,database first).
If you using EF 6 and code first approach you can use idea of base Entity class
public class BaseEntity
{
public DateTime ChangedAt {get;set;}
}
public class ConcreteEntity : BaseEntity
{
public string Name {get;set;}
}
Now ConcreteEntity has ChangedAt by inheritance.
If this solution not for you, please explain question with more details.

fluent nhibernate, inheritance and using derived list types

I am still on learning curve and I stuck. I am using fluent nhibernate with automapping. I have some conventions configured which works (someone else did it).
I have following structure:
LoyaltyProgram
UniversalProgram : LoyaltyProgram
OtherProgram : LoyaltyProgram
They using table per hierarchy which works, so conventions in general are OK.
I created some rules for storing customer points:
BasePointsRule
AmountPointsRule : BasePointsRule
TresholdPointsRule : BasePointsRule
BasePoints contains property
public virtual UniversalProgram UniversalProgram { get; set; }
I tried to do following, in class UniversalProgram:
public virtual ICollection<AmountPointsRule> AmountPointsRules { get; set; }
public virtual ICollection<TresholdPointsRule> TresholdPointsRules { get; set; }
I wish to be able to get and set them both.
I have set discriminator.
class BasePointsRuleMap : IAutoMappingOverride<BasePointsRule>
{
public void Override(AutoMapping<BasePointsRule> mapping)
{
mapping.DiscriminateSubClassesOnColumn("basepointstype");
}
}
But looking into database I have following foreign key created on table BasePointsRule:
alter table `BasePointsRule`
add index (UniversalProgramId),
add constraint FK_UniversalProgram_TresholdPointsRule_TresholdPointsRules
foreign key (UniversalProgramId)
references `LoyaltyProgram` (Id)
It saves bothe properties with correct discriminator, but during fetch AmountPointsRules get all records from BasePointsRule and proper bag for TresholdPoinstRules, but that it screams illegal access which seems to be correct, as AmountPoinstRules got all.
When I put abstract on BasePointsRule, there are two tables on database, foreigns keys properly referencing UniversalProgram and this works like a charm.
Question: is it possible to somehow override automappings to... i do not know ... set two constraints (for Amount and Treshold) or one for its base class?
consider if you really need two strongly typed collections instead of using LINQ's .OfType<>(). If you do then add a filter condition
class BasePointsRuleMap : IAutoMappingOverride<UniversalProgram>
{
public void Override(AutoMapping<UniversalProgram> mapping)
{
mapping.HasMany(x => x.AmountPointsRules).Where("basepointstype='AmountPointsRule'");
mapping.HasMany(x => x.TresholdPointsRules).Where("basepointstype='TresholdPointsRule'");
}
}

What is the quickest way to query a database with LINQ?

I'm reading a WROX book on LINQ and the author is performing LINQ on a database. Essentially he is accessing the database as an object as shown in the code below.
But I don't see how he expects to "access the database as an object", even the downloaded code gets an error on "db.DirectoryInformation" saying "DirectoryInformation" is unknown.
What am I missing? I would think I first need to create LINQ-to-SQL classes or an ADO.NET EDM or is there even a more direct way to hook LINQ up to a database, i.e. just by creating a database class and that inherits from DataContext?
AdventureWorks db = new AdventureWorks("Integrated Security=sspi");
...
[Database(Name = "AdventureWorks")]
public class AdventureWorks : DataContext
{
//public Table<DirInfo> DirectoryInformation;
public AdventureWorks(string connection) : base(connection) { }
public Table<DirectoryInformation> DirectoryInformation;
}
You can download the whole code here, chapter 1, LINQ.sln.
Look at the end of the Form1.cs source file, the LINQ to SQL database is declared using attributes:
[Database(Name = "AdventureWorks")]
public class AdventureWorks : DataContext
{
//public Table<DirInfo> DirectoryInformation;
public AdventureWorks(string connection) : base(connection) { }
public Table<DirectoryInformation> DirectoryInformation;
}
[Table(Name = "DirectoryInformation")]
public class DirectoryInformation
{
[Column(DbType="varchar(50)")]
public string DirectoryName;
[Column(DbType = "varchar(255)")]
public string DirectoryDescription;
}
Providing the settings with the project define a connection string, this is all you need for a simple mapping of the DirectoryInformation type to the DirectoryInformation table in the AdventureWorks database.
Oh, absolutely you can use vanilla objects with LINQ-to-SQL; you don't even need to subclass DataContext - but you do need to tell it about your model. This is often done with attributes on members (for columns) and types (for tables), but can also be done with an external mapping file (xml). I wonder if they are just over-abbreviating for simplicity... for example, I suspect that the table should be a property:
public Table<DirectoryInformation> DirectoryInformation {
get { return GetTable<DirectoryInformation>(); }
}
The whole "dbml" thing is just there as a designer tool to help you generate the classes; the important code is just decoracted classes (with some conventions on things like navigation properties to make life simper to use). That said, for "quickest": use the designer.

Categories

Resources