oop asp.net classes for sql server queries - c#

In sql server, I have Students and Departments tables.
I want to get Student records from Student table; with their Department data from Departments table(so i joined them) and show them in an asp.net page.
In asp.net I created a Student class type to use in list in asp.net codebehind.
The list, takes Student class type data like this:
List<Student> lst = new List<Student>();
But I need to get Students with their Department datas. So I created a custom class in asp.net side called StudentsAndDepartments.
Now the list takes this class:
List<StudentsAndDepartments> lst = new List<StudentsAndDepartments>();
My question; do I have to create, for every query I make, an another new custom class?
If I create a custom class for every query I use, there are being too many classes inside the solution.
I think I'm doing wrong..
What should I do?
Thanks for helping..

You do not create a "StudentsAndDepartments" class.
What you are doing here is trying to "flatten out" the domain model, and use one class to represent something that is better defined as a relationship.
You create your domain model. And relate them.
public class Student
{
public string LastName
/* the above is an example 'scalar' property on the Student. you'll have others like FirstName, StudentIdenficationNumber, etc, etc. */
/* below is the 'relationshiop' property, use one of the two below but not both */
public ICollection<Department> Departments;
/* or */
public Department ParentDepartment;
}
public class Department
{
public string DepartmentName
public ICollection<Student> Students;
}
Then you "hydrate" the domain model.
Now this is where things can really vary.
Entity Framework with POCO can do this.
ADO.NET can do this. You write "Serializers" which convert IDataReaders into your object model. This is manual-mapping.
With ADO.NET, you may write different stored procedures...
dbo.uspStudentsGetAllWithParentDepartments
dbo.uspDepartmentsGetAllSimple
dbo.uspDepartmentsGetAllWithChildrenStudents
something like that.
Now, where I digress from others usually.
I do NOT write JOIN SQL statements.
I write 2 separate SQL statements (in ONE stored procedures) to get my data.
dbo.uspStudentsGetAllWithParentDepartments
would like like this
Select st.EmpKey, st.LastName, st.FirstName from dbo.Student st
Select dept.DepartmentKey, dept.DepartmentName from dbo.Department dept where exists (Select null from dbo.Student innerStud where innerStud.ParentDepartmentKey = dept.DepartmentKey )
Now, Entity Framework can do this sql-writing for you, but it is a start-up cost if you've never seen it before.
What my Microsoft-only friends won't mention is that EF does not support the .Merge() function like NHibernate does (another ORM tool). Which is a deal breaker to me. But that's a deeper discussion.
Define your domain-objects, their relationships, and then ask questions about "what's the best way to hydrate my domain-model based on my current skill-sets" (or without the skillset part if you're open to new ways)
Here is a link to another answer I posted...which is the serializer code for the ado.net way of hydrating your objects.
Why is DataTable faster than DataReader

Related

Entity Framework 6 big query in inheritance

I have an inheritance strategy Table per Type (TPT) with an abstract class "Task" with a lot of concrete classes (like 30 classes).
When I try to show a worklist of "to do tasks", so asking EF for the abstract class, or when I try to get a generic task by ID, EF makes a 10000 lines query joining every concrete class, that result very slow.
There is a way to configure EF to avoid the big query?
In the worklist method, I need only fields of the abstract class.
This is my code:
public Task GetTaskById(int id) {
return this.repository.Tasks.Where(t => t.ID == id).FirstOrDefault();
}
public IQueryable<Task> GetWorklist() {
return this.repository.Tasks.Where(t => a.ActivitySate.Code == ActivitySateEnum.TO_DO);
}
Thank you
Relational databases don't handle the concept of inheritance very well. Several strategies have been invented for entity framework to mock inheritance.
Which strategy suits you most depends on which kind of queries and updates you perform most often.
Suppose you have a class Person, and two specific kinds of Persons: Teachers and Students. There are two popular strategies to implement inheritance
Table per Type (TPT)
Every class is represented in a separate table. In our example three tables are created: a Persons table, a Teachers table with a foreign key to the Person it is, and a Students table with a foreign key to the Person data of the Student.
If you query: "give me the Persons that ...", only one table needs to be inspected. However, if you ask: "give me the Students who ...", then a join between the Persons table and the Students table is needed.
If you add / update / remove one Student, then two tables need to be updated.
If in future one column needs to be added to one of the classes, only one table is involved.
Adding a new kind of Person, like Sponsors is easy, however they have to be Persons and inherit all Person columns. If later you decide that a Sponsor is not a Person anymore you are in trouble.
This method is most suitable if you ask far more often for Persons than for Students and Teachers. It is less suitable if you ask quite often for Students with Person data. Also if you add / remove / update Students very often, don't use this method.
Also use this method if you need to create a Person that is neither a Teacher nor a Student yet, but later may become one of them, or maybe both Teacher and Student
Table per concreate class (TPC)
There is no separate table for Persons. All Person properties are in the Teachers table as well as in the Students table.
Querying "Students who ..." or "Teachers that ..." will only involve one table. However querying "Persons that ..." will involve the concatenation of data retrieved from the Students table with data retrieved from the Teachers table.
Add / Remove / Update a Student will always involve one table.
Adding a column to a Student involves changing one table. However adding a column to Person involves changing both Students and Teachers tables.
Adding a new kind of Person, say Janitors or Sponsors is easy. It won't be a problem if in future a Sponsor is not a Person anymore.
You can't create a Person, it always has to be either a Teacher or a Student. A Student never can become a Teacher, he will become a new Person (which seems a bit ironic :-). No Student can be a Teacher as well.
Use this method if you seldom ask for Persons who ..., but most often ask for Students who ...
Conclusion
The strategy to choose for your inheritance depends on how you will use your tables.
You seem to have 30 kinds of Persons implemented as TPC (no separate Persons table). If you ask for Persons who ..., your database has to concatenate the results from all 30 tables.
If you think this is by far the most used kind of query, consider changing the inheritance strategy to TPT. Whether you should do this depends on whether the database is already filled with a lot of data or not. If you are using code-first, you'll probably start with a fairly empty database.
The problem is that you use a ba repository that does not return IQueryable, so it doesn ot allow EF to actually use the filters you DO have (you do, right?) where you limit the returned data to only some fields.
So, what is lett is materialize the entity (which is SOOOO standard for the repository antipattern). And there you go.... for that.... It NEEDS to join TPT. Those are 30 classes, which mean 30+ tables. First, the query likely has no 10k lines. Second, this is normal and smallish for really complex SQL (which you DO have here). Third, you set that up yourself - yes, this is what is needed to pull in all the data.
Solution? Get rid of the suplus repository (DbContext IS a repository, you know) and then make the filter based on the base type and make sure to project ONLY the needed fields into an anonymous class, so EF CAN do optimization.

Selecting different tables in nHibernate

I need to execute a query that will return N tables. in my program, i have the following tables (some of them):
TABLES:
HM_RECEIVE;
HM_SEND;
SM_RECEIVE;
SM_SEND;
P_SLAB;
P_SLAB_PDO;
...
Entities:
HMreceive;
HMsend;
SMreceive;
SMsend;
PSlab;
PSlabPDO;
...
I have two questions, and this would be nicer if i could accomplish it using only one criteria:
How do I select all tables? In first moment I believe there's no need to match IDs, but if changes anything I really would like to know;
Is there a way to select only HM and SM tables, ignoring all others?
Thanks in advance.
Edit:
How I do something like: select * from HMReceive, SMReceive, HMSend, SMSend?
If the tables have similar layout, you could use inheritance.
Define the classes similar to:
public class HMReceive : BaseClass
public class HMSend : BaseClass
public class SMReceive : BaseClass
public class SMSend : BaseClass
and you can use HQL to
select * from BaseClass
or use criteria to query against BaseClass. The result will be an IList but each entity returned will consist of the actual type HMReceive, HMSend, SMReceive, or SMSend.
I'm not very sure about your requirement, but using NHibernate, there are several ways to fetch multiple tables in a single query:
Using eager fetching if your tables connect with each other. Following query will fetch child records along with their Parent:
session.QueryOver<Child>().Fetch(child => child.Parent).Eager.List();
If the tables are not connect with each other, and your database is Oracle, then you are out of luck. But with MS SQL Server, you can use Future() to make multiple queries to go to database at once:
// Future() returns a lazy enumerable, not actually queries the database.
var childs = session.QueryOver<Child>().Future();
// NHibernate will populate the lazy enumerable once it being enumerated,
// or when it has to hit the database anyway, like when a call to List() happen:
var parents =session.QueryOver<Parent>().List();
Hope this help.
It sounds like you are asking for a way to fetch pretty much all of the data in the database. You really should just fetch only the data that you need. That said, sometimes it is useful to be able to fetch data from tables without having to explicitly name the tables that you want to fetch from. For example, you may want to write a unit test that simply verifies that the NHibernate mappings correctly match your database schema. Ayende has a blog post illustrating how to write such a test. This is a slightly modified version of that test:
[Test]
public void SchemaShouldMatchMappings()
{
// `GetAllClassMetadata` returns a collection of all of the mapped entities.
foreach (var entry in _sessionFactory.GetAllClassMetadata())
{
// Build a query that fetches this entity...
_session.CreateCriteria(entry.Value.EntityName)
// ... but tell it to just check the schema and not actually bring any back.
.SetMaxResults(0)
// Execute the query.
.List();
}
}
I think you can use a loop similar to the above as a starting point for what you are trying to accomplish. I'm not going to actually post a code example that fetches all of the data in the database because I don't want to encourage people to do bad things - but this should be enough to get you started.

Using existing database and EF code-first, mapping a lookup table to entity

I am using entity framework, code first, 4.0, hitting an existing legacy database for read-only access. The database is normalized, so
Table [Event]
[ID]
[Date_Entered]
[Event_Status_Key]
Table [Event_Status]
[Event_Status_Key]
[Event_Status_Description]
My class looks like
public class Event
{
public DateTime DateEntered { get; set; }
public string StatusDescription { get; set; }
}
This is a WCF service layer application.
My two questions:
Is there any easy way to populate the status description without creating a second Dictionary-type object? I've seen questions like this: Entity Framework Mapping to Lookup table, but they seem to be focused on object to object, and I really just want a primitive. I'd prefer using the fluent API as opposed to attributes.
When the data is loaded, is any of the data cached at the code layer? Or does each check on the StatusDescription mean a separate call on the [Event_Status] table?
Edit: A possible (more subjective, which is why I didn't bring it up) third question is how close should the data entities match the database. Is it always a one-to-one field/table? Is what I'm doing (joining two tables into one data entity obejct) bad?
Thanks.
Entity framework expects that you will map both tables as separate entities and use projection in your query:
var query = from e in context.Events
select new WcfEvent // Your original Event class is just DTO
{
DateEntered = e.DateEntered,
StatusDescription = e.EventStatus.EventStatusDescription
};
This example expects correctly one-to-one mapping of your Event and Event_Status tables.
If you need any kind of caching you will have to implement it yourselves. Projected results are not even tracked by the context.

ASP.NET MVC 3 with already built SQL Server on different databases

I'm creating an ASP.NET MVC3 project in C# that is using an already existing SQL Server database.
The SQL Server has different databases, one for each customer. Each customer database has numerous tables, but I'm interested in only one table.
So, I'm interested in retrieving (and not updating or deleting) data from the same table of every customer.
This is the database configuration example:
DatabaseCustomerName1
- TableNeeded
DatabaseCustomerName2
- TableNeeded
DatabaseCustomerNameN
- Tableneeded
The question is... how do I create the model?
Knowing that If I had to do it for just one customer I would create the model basing on the fields of the tables, how can I manage the situation of having multiple customers?
Thanks in advance.
Attila
You should have an interface for Repository class
for example and different implementations for each custumer data base
internal interface IProductRepository
{
IEnumerable<Product> GetAll();
}
class ProductRepositoryCustumerOne : IProductRepository
{
public IEnumerable<Product> GetAll()
{
//code to retrieve data
}
}
class ProductRepositoryCustumerTwo : IProductRepository
{
public IEnumerable<Product> GetAll()
{
//code to retrieve data
}
}
after you can inject with IoC container what implementation you need
Let me just clarify your question, are you saying you've got
a number of customers with a database each?
So...
Databases
Customer A
Customer B
And for each of those customers you're saying you have a table that you want to access so you have
Customer A > TheTable
Customer B > TheTable
So you're asking, how can you create a Model that will work for any customer to access TheTable?
Is that correct?
What about creating a Sql View over all tables based on a select link this:
Select 'Customer 1' as Customer, c.* from FirstDb.dbo.Cusotmers c
Union Select 'Customer 2' as Customer, c.* from SecondDb.dbo.Cusotmers c
Union ...
Than you can handel this view with e.g. EF or linq to sql.
Is it safe to assume you are using Entity Framework? Is the schema in all the databases the same?
You should be able to create your model against one of the databases. Then whenever you want to select a different customer you will need to change the Initial Catalog (or equivalent) value in the connection string before you create your data context.
I don't have any code handy at the moment. Does this help?

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