I have read mythz's post here about how ORMLite can read anything up from SQL and fit it into a POCO of the same shape. That is great.
On the other hand, how does ORMLite handle these "View POCOs" when saving them back into the database? Since they are not tables, they may be views or they may be just any sql select queries like that:
var rows = dbCmd.Select<ShipperTypeCount>(
"SELECT ShipperTypeId, COUNT(*) AS Total FROM Shippers GROUP BY ShipperTypeId ORDER BY COUNT(*)");
There's nothing special about the POCOs you use with OrmLite, they're not tied or related back to any underlying tables and there's no hidden magic state that OrmLite caches in between calls so it knows what fields map to.
With every DB call OrmLite just uses the POCO to create the appropriate SELECT, INSERT, UPDATE or DELETE statement based on the schema definition of the type. The INSERT Apis shows some examples of this.
It's best to think of OrmLite as just turning your POCO into an SQL statement, which is what it does. So trying to insert a ShipperTypeCount will attempt to insert a record into a table called ShipperTypeCount unless it has an [Alias("UseTableNameInstead")] attribute which it will use instead.
Related
I have a problem where I have to get the column names and their values from all the Tables in my schema and show that the result in a grid.
I have used the direct approach for this but I have to implement the SqlSiphon structure. For this I have to make getters and setters of each of the column of each Table in the schema which is impossible.
What should I use to get the Column names and their values dynamically from the table.
SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = '" + #Tablename1 + "' AND TABLE_SCHEMA='dbo'"
What will be the best dynamic solution?
And what will be Best to use List , Dictionay or something like 2d Array which will give the column names as well as column values?
A few suggestions:
I'm not completely clear on what you're trying to achieve, but consider using an ORM (Linq2SQL, WEF, NHibernate)
In .NET, a suitable type to represent a database table would be a DataTable
Edit: After a few more re-reads I think I understand what you're asking - you already have a database/schema and you want to automatically create the entity classes needed by SqlSiphon. This is called "database-first" (as opposed to model-first). However, from a brief scan of the SqlSiphon documentation it appears it does not support database-first. Is this why you are trying to put the columns into a grid - to make it easier to manually create the entity classes for SqlSiphon?
Edit2: Note that trying to use an ORM on top of a database whose schema is frequently modified will be problematic. My next guess is that you're trying to figure out how to create an entity class in SqlSiphon which you can use to retrieve database schema information like table columns? I'm still struggling to understand what you're actually asking here - perhaps you can update your question?
Edit3: I think the answer to your question is take a different approach to your design - ORM's like SqlSiphon are not intended to be used to retrieve and modify the database schema itself.
Might be worth taking a step back an comparing against how other people solve similar problems.
Typically, each table on a database represents an entity, and you also have a class per entity, and you may use an ORM system to avoid duplication of work. So, in a typical system, you have a table for customers, and a table for invoices, and a table for invoice lines, etc. and then a class that represents a customer, a class for an invoice, a class for an invoice line, etc. As you later add functionality (and possible columns/properties) you change the classes, rather than just seeing what columns are on the database - you can of course decorate these with XML documentation and get Intelisense goodness.
There are many ORM systems out there, and each have their strengths and weaknesses, but I personally like LINQ to SQL for adding onto an existing data model.
With EF I can return a collection of objects like so
entities.Customers.ToArray();
And I can include other tables, so I can effectively get 2 result sets back in the one query
entities.Customers.Include("Invoice").ToArray();
or if I have some custom SQL I can achive a similar result:
SqlDataReader reader = GetReaderFromSomewhere("SELECT * FROM Customer");
entities.Translate<Customer>(reader).ToArray();
But how do I get multiple results back from my own SQL? What I was thinking was something like this
SqlDataReader reader = GetReaderFromSomewhere("SELECT Customer.Name AS CustomerName, Invoice.Number AS InvoiceNumber FROM Customer JOIN Invoice ON Customer.ID = Invoice.CustomerID");
entities.Translate<Customer>(reader).Include<Invoice>().ToArray();
In the above example I have prefixed all the returned data with the table name so that the Translate method can know which columns belong to which tables. I'm presuming the Tranlate method does not support this but EF must do something similar when the include method is called. So my question is, how can I get the functionality of Include when using Translate?
AFAIK you can not do that manually. What EF does is, it dynamically generate a class based on the LINQ query(and the Includes) that can materialize entities. Basically this class knows which columns will be mapped to which properties.
However you can use a micro ORM like Dapper which can do Multi Mapping. But this will only work for querying. So change tracking and CUD operations will not be available.
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.
I have a library which uses EF4 for accessing a SQL Server data store. For different reasons, I have to use SQL Server specific syntax to read data from the store (for free text search), so I have to create the SQL code by hand and send it through the ExecuteStoreQuery method.
This works fine, except that the query uses joins to request several tables aside the main one (the main one being the one I specify as the target entity set when calling ExecuteStoreQuery), and EF never fills up the main entity's relationship properties with the other table's data.
Is there anything special to do to fill up these relationships? Using other EF methods or using special table names in the query or something?
Thanks for your help.
Executing direct SQL follows very simple rule: It uses column from the result set to fill the property with the same name in materialized entity. I think I read somewhere that this works only with the the main entity you materialize (entity type defined in ExecuteStoreQuery = no relations) but I can't find it now. I did several tests and it really doesn't populate any relation.
Ok so I'll write here what I ended up doing, which does not looks like a perfect solution, but it does not seem that there is any perfect solution in this case.
As Ladislav pointed out, the ExecuteStoreQuery (as well as the other "custom query" method, Translate) only maps the column of the entity you specify, leaving all the other columns aside. Therefore I had to load the dependencies separately, like this :
// Execute
IEnumerable<MainEntity> result = context.ExecuteStoreQuery<MainEntity>(strQuery, "MainEntities", MergeOption.AppendOnly, someParams).ToArray();
// Load relations, first method
foreach (MainEntity e in result)
{
if (!e.Relation1Reference.IsLoaded)
e.Relation1Reference.Load();
if (!e.Relation2Reference.IsLoaded)
e.Relation2Reference.Load();
// ...
}
// Load relations, second method
// The main entity contains a navigation property pointing
// to a record in the OtherEntity entity
foreach(OtherEntity e in context.OtherEntities)
context.OtherEntities.Attach(e);
There. I think these two techniques have to be chosen depending on the number and size of generated requests. The first technique will generate a one-record request for every required side record, but no unnessecary record will be loaded. The second technique uses less requests (one per table) but retrieves all the records so it uses more memory.
nice job
is it possible to update a data base which doesn't have primary key column with a datagridview?(in a winform program)
i use sql express 2008,and wanna do this with dataset approach.
Cheers
Without knowing a significant amount about what exactly you are doing and how you are going about your problem the simple answer is. Yes…
The datagridview in the .Net framework allows for binding to Objects exposing public properties and implementing custom select and update methods. Therefore it allows you to implement your own custom update method if required and allows for you to perform the update based on any column in your underlying database.
You still need a unique column or a combination of columns to differenciate the various rows you are about to update. At the end of the day the DataLayer that is used to access the data will just do an ordinary sql update/insert on your data.
Just to have asked you but your data model seems kind of broken. I mean that a primary key or at least a unique column would be preferable in any case.
It's all about where your data is actually coming from, whether it's using datasets with plain-old-sql, some kind of ORM (NHibernate or Entity-Framework or whatever), typed datasets, linq-2-sql ...
Depending on your datasource you might have to introduce a primary key to your database.
The GridView actually doesn't care about that, in the end it's just displaying a list of data, and to the grid there is no such thing as a primary key. This only matters to the data access technique in order to know which row to update.