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?
Related
I am creating a WPF app and I have an existing DB that I would like to use and NOT recreate. I will if I have to, but I would rather not. The DB Is sqlite and when I add it to my data later and create a DataModel based on the DB, I get the model and the DB Context, however there are no methods created for CRUD or for instance .ToList() so I can return all of the items on the table.
Do I need to create all of these manually or is there a way to do it like the way that MVC can scaffold?
I am using VS 2017, WPF, EF6 and Sqlite installed with Nu-Get
To answer the question in the title.
No.
There is no click-a-button method of scaffolding out UI like you get with MVC.
If you just deal with a table at a time then you could build a generic repository that returns a List for a given table. That won't save you much coding, but you could do it.
If you made that return an iQueryable rather than just a List then you could "chain" such a query. Linq queries aren't turned into SQL until you force iteration and you can base one on another adding criteria, what to select etc etc for flexibility.
In the body of your post you ask about methods to read and write data. This seems to be almost totally unrelated from the other question because it's data access rather than UI.
"there are no methods created for CRUD or for instance .ToList() so I can return all of the items on the table."
There are methods available in the form of LINQ extension methods.
ToList() is one of these, except it is usual to use async await and ToListAsync.
Where and Select are other extension methods.
You would be writing any model layer that exposed the results of those though.
I'm not clear whether you are just unaware of linq or what, but here's an example query.
var customers = await (from c in db.Customers
orderby c.CustomerName
select c)
.Include(x => x.Orders) //.Include("Orders") alternate syntax
.ToListAsync();
EF uses "lazy loading" of related entities, that Include makes it read the Orders for each customer.
Entity Framework is an Object Relational Mapper
Which means it will Map your C# objects to Tables.
Whenever you are creating a model from bd it will create a Context Class which will in inherit the DbContext. in this class you will find all the tables in DbSet<Tablename> Tablename{get; set;}. Basically, this list contains will the rows. the operation performed on this list will affect the DB on SaveChange method.
Example for CURD
public DbSet<Student> Students { get; set; }
//Create
using (var context = new YourDataContext()) {
var std = new Student()
{
Name = "Aviansh"
};
context.Students.Add(std);
context.SaveChanges();
}//Basically saving it will add a row in student table with name field as avinash
//Delete
using (var context = new YourDataContext()) {
var CurrentStudent=context.Students.FirstOrDefault(x=>x.Name=="Avinash")
CurrentStudent.context.Students.Remove(CurrentStudent);
context.SaveChanges();
}
Note: on SaveChanges the change will reflect on Db
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
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.
I have a webpage and site using Linq. The page contains a gridview which shows customers and bound by a List (Of Customer).
I use the below code to get a single customer
Public Function GetCustById(ByVal id As Integer) As Customer Implements ICustomerService.GetCustById
Return DataContext.Customers.SingleOrDefault(Function(c) c.Id = id)
End Function
I then bind it to my gridview by passing all the customer IDs into the method. This displays all the rows as i need but i have one issue.
Some columns which are Foreign keys show up as 1,2 etc, Usually the way i have overcome this in the past ON DIFFERENT PROJECTS is by adding a sub query to my SQL query in the data layer but as you've guessed this is Linq so im not sure what is /not possible in order to get the Foreign Keys to display as values using Linq?
Im a little new to Linq so appreciate any help or articles that would help me with this.
Thanks
It is recommended to separate the view from the entity classes (or domain classes if you like). So you will define a view model class, say CustomerViewModel, and project your Customer into it.
I'm not sure how you get a list of Customers (getting each single customer by Id is highly inefficient) but somewhere there will be an IEnumerable<Customer>. Let's call it customers. Now you can do
From c in customers_
Select New CustomerViewModel With { Name = c.Name, ... }
But now you can add properties to CustomerViewModel that are not in Customer! For instance
Select New CustomerViewModel
With { Name = c.Name, TypeName = c.CustomerType.Name }
This CustomerType could be one of those foreign keys you want to show.
The result of the projection is an IEnumerable<CustomerViewModel> that you can show in the grid.
I have the following scenario: there are a database that generates a new logTable every year. It started on 2001 and now has 11 tables. They all have the same structure, thus the same fields, indexes,pk's, etc.
I have some classes called managers that - as the name says - manages every operation on this DB. For each different table i have a manager, except for this logTable which i have only one manager.
I've read a lot and tried different things like using ITable to get tables dynamically or an interface that all my tables implements. Unfortunately, i lose strong-typed properties and with that i can't do any searches or updates or anything, since i can't use logTable.Where(q=> q.ID == paramId).
Considering that those tables have the same structure, a query that searches logs from 2010 can be the exact one that searches logs from 2011 and on.
I'm only asking this because i wouldn't like to rewrite the same code for each table, since they are equal on it's structure.
EDIT
I'm using Linq to SQL as my ORM. And these tables uses all DB operations, not just select.
Consider putting all your logs in one table and using partitioning to maintain performance. If that is not feasible you could create a view that unions all the log tables together and use that when selecting log data. That way when you added a new log table you just update the view to include the new table.
EDIT Further to the most recent comment:
Sounds like you need a new DBA if he won't let you create new SPs. Yes I think could define an ILogTable interface and then make your log table classes implement it, but that would not allow you do GetTable<ILogTable>(). You would have to have some kind of DAL class with a method that created a union query, e.g.
public IEnumerable<ILogTable> GetLogs()
{
var Log2010 = from log in DBContext.2010Logs
select (ILogTable)log;
var Log2011 = from log in DBContext.2011Logs
select (ILogTable)log;
return Log2010.Concat(Log2011);
}
Above code is completely untested and may fail horribly ;-)
Edited to keep #AS-CII happy ;-)
You might want to look into the Codeplex Fluent Linq to SQL project. I've never used it, but I'm familiar with the ideas from using similar mapping techniques in EF4. YOu could create a single object and map it dynamically to different tables using syntax such as:
public class LogMapping : Mapping<Log> {
public LogMapping(int year) {
Named("Logs" + year);
//Column mappings...
}
}
As long as each of your queries return the same shape, you can use ExecuteQuery<Log>("Select cols From LogTable" + instance). Just be aware that ExecuteQuery is one case where LINQ to SQL allows for SQL Injection. I discuss how to parameterize ExecuteQuery at http://www.thinqlinq.com/Post.aspx/Title/Does-LINQ-to-SQL-eliminate-the-possibility-of-SQL-Injection.