Posts Tagged ‘Databases in general’
Nedávno se na Builderu lehce rozjela diskuze, ačkoli v threadu na odlišné téma, jestli sloupce v SQL příkazech vyjmenovávat nebo ne. Nedá mi to a přispěju taky svou troškou.
Já bych “problém” rozdělil na dvě části. První je SQL kód v aplikaci. Druhou je kód v rámci pohledů, spouští, uložených procedur atp.
V prvním případě jasně a striktně sloupce vyjmenovávám. Jednak mám pocit, že to přidá na přehlednosti. Nejenom v rámci zápisu, ale i když později človek kód prochází a třeba něco přidává – vidí co do aplikace přichází a jak se to jmenuje. Případně se tak triviálně (aka Find) dají hledat závislosti. A jednak si myslím, že to ukazuje, že člověk nad výsledkem přemýšlel. Samozřejmě platí i to klasické, že při změně struktury nedochází k neočekávanému chování, kdy aplikace tahá sloupce, o kterých nemá ponětí a nedokáže je využít.
V druhém případě to již tak striktně nemám, ačkoli stále jsem daleko od volnosti. Sloupce opět vyjmenovávám, ale mám pár – v pro mě velmi opodstatněných, triviálních případech – “povolení”, kdy nevyjmenovávám. V zásadě se jedná o případy, kdy daný objekt jen k datům něco přidává resp. je překlápí. Typicky pohled, který k sadě přidává třeba RANK. Nebo trigger kopírující data 1:1 navíc do jiné tabulky. Potom si dovolím použít * (a někdy i přesto sloupce vyjmenuji). Jinak standardně vyjmenovávám.
Kdejaký nástroj vám všechny aktuální sloupce dokáže vygenerovat: Flamerobin, SQL Server Management Studio, IBExpert, Database Workbench, … Slušně si je naformátovat do zápisu je pak triviální.
Proč psát něco, čehož chování se může změnit, aniž bych se o tom ïmplicitně dozvěděl. A samozřejmě stále platí to co jsem napsal výše o přemýšlení nad tím co píšu.
Last 24 hours was interesting. Almost everybody doing something with databases and .NET was talking about new Microsoft.Data.dll. And there has been recently a lot of clarification (i.e. this or this) (check your favorite search engine for more) what it is and what it is not and who’s target audience.
From what I read emerges that it’s focused on starting developers who may not even be interested in being “real” developers. Somebody who wants to just put some site together and run. Be close to PHP world style of working. Together with WebMatrix.
I’ll not think about whether it’s good for MS’s ecosystem or not. Although I see the the points as valid, I still don’t get it. If you’re a beginner, really beginner and you wanna create some site, would you spend some time on creating it or rather try to install i.e. WordPress. It’s probably the same challenge, but the result will be different. Not taking into account, that you would still need to have at least basic knowledge of (X)HTML, programming and databases and SQL when doing it on your own, isn’t it? OK, so maybe the novice just wants to create some site on his/her own. Learn something. Improve own skills. But all this stuff isn’t going to give him/her touch of how it’s really done. You’ll be learning something that useless for bigger, real-world, applications. Umm, than he or she may not be interested in expanding skills, really just create something for fun, you might think. But do you really think this case exists? Doesn’t it sooner or later fall into one of two categories above?
And the dynamic point of view? I read somewhere that the target audience is expected to use not so sophisticated editors etc. (BTW isn’t Visual Studio Express free???). But that’s not what bothers me. What bothers me, it’s the lack of compile-time checking (which is what I damn like when I develop). You’ll upload the site to web a you’ll have to check a lot of code (pages) to see whether it works. The refactoring is harder; ahh damn, that’s not what the target audience is going to be doing or will they? Don’t forget the find&replace is refactoring as well, and here the compile time checking is really useful?
On the other hand, maybe it’s a good idea, and only because we’re not novices and the “product” isn’t enterprise ready, we should understand it and try not to judge it with enterprise-ready eyes. Because we are maybe spinning in our own world not seeing outside the box. But I personally still think the idea how it’s done it’s wrong.
The new Microsoft.Data.dll seems to be very “interesting”.
I generally agree, that pure raw ADO.NET is more verbose than the shown example. And that’s all. On the other hand, everybody using pure raw ADO.NET have written couple of helper methods already. And directly for his/her desired approach, with non-dynamic typing. This isn’t going to make anyones life easier. As an experiment with dynamic keyword it’s nice. But a stuff used in real world deployed application? No so sure.
Wanna go easy path? Go LINQ to SQL of Entity Framework with just 1:1 model generated from database (if we’re on MS’s stack, nHibernate or LLBLGen Pro will do the work as well). Wanna go pure SQL, all under own control? ADO.NET is waiting for you. But this, this looks like kind of mixture of both, but nothing good resulted.
By the way, will there be any support for parametrized queries? I hope so. Because if not, then it’s even more funny than it already is.
UPDATE: There’s a support: http://blog.andrewnurse.net/2010/08/03/MicrosoftDataItrsquosNotAsEvilAsYouThink.aspx.
For me it’s a step back. Or am I missing something?
Recently I’ve got to think about ER world and OO world. There’s a lot of people around there who understand ER or OO world very deeply. In fact ER world is well formalized, described and has a strong mathematical background. A lot of theoretical work is behind OO as well. But what about ORMs?
Is it about the fact we understand both worlds correctly and it’s good we’re trying to bridge them using the power of machines instead of our hands and brains all over again or the exact opposite? Trying to wrongly create something that automagically does this bridging even if the bridge itself will be bloated, slow and creating ugly results?
Have you ever seen query from Entity Framework, LLBLGen Pro, Hibernate, nHibernate, …, name yours? Don’t blame the tool. I think any of them is doing great job translating the query from some king of object oriented way of expressing what I want to i.e. SQL. The problem is, that we’re not querying database, but objects mapped to database objects. Sometimes with very clever mapping. The tool then has to reason about some general transitions from objects to tables and then creating the query. Sure a room for improvement is here. But is it worth?
What other options do we have? Object databases (or post-relational)? Relational programming (probably not)? Maybe just the ORMs idea is wrong. Maybe the bridging is good, and we just need to start from the other end and do it differently. Maybe allow lower the abstraction for those who understand both worlds. And remember these worlds proved self to be very useful doing what they were designed to do. So we just need to find a way to work in both with less friction; or did we find it?
Scott Guthrie recently posted article about New Embedded Database Support with ASP.NET. This made me think about other options, Firebird in particular, and advantages and disadvantages. What I’m going to do is to very shortly introduce Firebird Embedded here and then compare it with features Scott wrote in his article.
Firebird Embedded, shortly, is Firebird database server in one DLL. No need to install etc., just load this DLL and use it. To be precise, there are some other DLLs, i.e. to support national charsets, but it’s still in under 10MB all. The database itself is built from same sources as “full” server and it’s not limited in any way.
Works with Existing Data APIs – as I said, Firebird Embedded is based on same codebase as “full” server, thus the SQL and API is same. And not only this, the ADO.NET provider for Firebird works with it and you’re programming using same thinking.
No Database Installation Required and Database Files are Stored on Disk – databases created by Firebird Embedded are stored wherever you want, with any extension. Firebird itself doesn’t have any master database, thus even the “full” server works with any (valid database) file.
Shared Web Hosting Scenarios Are Now Supported with SQL CE 4 – sure you don’t need to install anything with Firebird Embedded, that’s why it’s called Embedded. And not only this, from version 2.5, you can open database from different processes, i.e. IIS worker process and Apache workers or some console application doing something in background.
Visual Studio 2010 and Visual Web Developer 2010 Express Support – as the tool set for Firebird Embedded is exactly same as for “full” Firebird, you can use DDEX (aka Server Explorer support), Entity Framework (LINQ), …
Supports Both Development and Production – this is something I’m silently expecting. But yes, you can do the same with Firebird Embedded too.
Easy Migration to SQL Server – ahh, my favorite point. The Firebird Project has of course whopping number of tools to support migration from Embedded to “full”. The most used is … nothing. The databases are fully compatible and you can switch servers without any other tools, migration, conversion, … Just place it where you want it and connect to it, either with “full” or Embedded Firebird. And to switch your application? Again nothing. Same ADO.NET provider, just change connection string, if needed. Mostly you’ll add server IP address and maybe different path and manually switch server type, if you want. Really the migration is so simple. It is one minute task and thanks to same tool set, no matter what you version your targeting during development, your application will work with the other as well without any additional effort.
You like Firebird Embedded? I do, a lot. SQL Server Compact Edition 4 looks promising, but Firebird has something to offer as well. And recall, it’s based on same sources as “full” Firebird, very mature codebase, examined with tons of installations.
The EDM designer in Entity Framework 4 has a “nice” new feature. You, know in EFv1 you was forced to map all three CUD procedures or nothing. If you didn’t do that, the validation feature told you. If you do the same in EFv4 the validation succeeds. Great, you may think. Finally I can use just procedures I really want (if you whatsoever want to use SPs and tight the logic into database when using ORM) to use and the rest will be generated for me. But nope. In fact the error will be thrown in runtime(!!!).
It’s described in documentation. But I couldn’t help but wonder, who did this decision??? I hate every error in runtime, I like my static compile time checking. It’s much safer, in my opinion.
I don’t know whether it’s somewhere specifically pointed, but the ObjectContext in Entity Framework v4 has two (three) new handy methods. And I like these.
It’s kind of escape hatch similar to DefiningQuery. First method is Translate<T>. It takes DbDataReader and materializes the data back into entities. It’s similar to Materialize method from EFExtensions. If you some code in pure ADO.NET and you don’t have time or resources to redo it in EF (or it’s way easier old way) you can rewire the result into existing objects. I like it. Whenever I’ll feel I need to get dirty (and probably due to performance reasons) I can do it pretty easily.
using (testovaciEntities ent = new testovaciEntities())
{
IDbConnection conn = (ent.Connection as EntityConnection).StoreConnection;
conn.Open();
using (IDbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "select * from master";
using (DbDataReader reader = (DbDataReader)cmd.ExecuteReader())
{
MASTER[] result = ent.Translate(reader).ToArray();
Console.WriteLine(result.Length);
}
}
}
The other method is similar and simplifies the process of getting dirty if you simply need to run you fine tuned query with neat and sexy constructs.
It’s ExecuteStoreQuery<T>. This method simply allows you to run any sql command directly in store language (thus you can use all features your database offers) and fetch and materialize back resulting entities. Similar to this is ExecuteStoreCommand which is similar to ExecuteNonQuery from pure ADO.NET. But you can do this without the method easily too, the method is just more convenient.
BTW also note that the Translate method isn’t adding the entities into context, it’s just about fetching and materializing.
Yesterday there was a question in one list I’m following. Simply to share some recommendation for tool being able to reverse engineer the database structure and show some E-R diagram.
After I get time to reply with some suggestions, idea came to my head. The EDM designer is actually kind of reverse engineering tool. Did you realized that?
As the EF support for major database platforms is available it’s easy to get a basic overview of the database structure without leaving Visual Studio. Sure it doesn’t have some cool features of specialized programs, but on the other hand it’s already in VS (Express edition is free) and you don’t have to buy and install another product (if you’re not doing this often, but then you’re probably using the specialized program).
From time to time I have to run two or more queries that I know will always be two or more – like some first/skip records and also total count. If you write it as two queries and execute, that means two round trips to database. Although it may not matter if the network latency is very small, why not to challenge myself and try to find some workarounds.
Sure you can create some stored procedures and get the data back from these, but I was thinking about more LINQ to Entitiesish way. I recalled a way I one time used inside one project. Although it was done in pure SQL, it, as it turned out, works, kind of, for LINQ to Entities as well.
The idea is using “one row table” and put the queries as columns. Let me demonstrate:
select
(select foo, bar from table1 where ...),
(select baz, foo from table2 where ...)
from OneRowTable;
Where the OneRowTable can be specially created table or i.e. for Firebird RDB$DATABASE or for Oracle Database dual. It isn’t the nicest SQL (and also challenges optimizer), but works. In columns as queries you can put anything you want as long as it is syntactically correct.
OK, what about the Entity Framework or LINQ to Entities respectively. I created the “one row table” first:
create table OneRowTable(x bit primary key);
insert into OneRowTable values (0);
The table needs to have the primary key to be able to import it into entity model, the datatype doesn’t matter (I was using MS SQL, hence the bit).
What about the queries? Similar approach:
var allinone = context.OneRowTable.Select(_ => new
{
AData = context.a.Where(a => a.x.HasValue && a.x.Value > 10).Select(a => new { A1 = a.id, A2 = a.id * 2 }),
BData = context.b.Where(b => b.id < 999).Select(b => new { B1 = b.id, B2 = b.y }),
});
string query = (allinone as ObjectQuery).ToTraceString();
var data = allinone.First();
var adata = data.AData;
var bdata = data.BData;
The a and b are my testing tables. You can check there’s only one query executed. Encapsulating this into some method is only piece of cake.
And how the query looks like? Well for my MS SQL test:
SELECT
[UnionAll1].[x] AS [C1],
[UnionAll1].[C2] AS [C2],
[UnionAll1].[C1] AS [C3],
[UnionAll1].[id] AS [C4],
[UnionAll1].[id1] AS [C5],
[UnionAll1].[C3] AS [C6],
[UnionAll1].[C4] AS [C7],
[UnionAll1].[C5] AS [C8],
[UnionAll1].[C6] AS [C9]
FROM (SELECT
[Project1].[C2] AS [C1],
[Extent1].[x] AS [x],
1 AS [C2],
[Project1].[id] AS [id],
[Project1].[id] AS [id1],
[Project1].[C1] AS [C3],
CAST(NULL AS int) AS [C4],
CAST(NULL AS int) AS [C5],
CAST(NULL AS varchar(1)) AS [C6]
FROM [dbo].[OneRowTable] AS [Extent1]
LEFT OUTER JOIN (SELECT
[Extent2].[id] AS [id],
[Extent2].[id] * 2 AS [C1],
1 AS [C2]
FROM [dbo].[a] AS [Extent2]
WHERE ([Extent2].[x] IS NOT NULL) AND ([Extent2].[x] > 10) ) AS [Project1] ON 1 = 1
UNION ALL
SELECT
2 AS [C1],
[Extent3].[x] AS [x],
[Extent4].[id] AS [id],
CAST(NULL AS int) AS [C2],
CAST(NULL AS int) AS [C3],
CAST(NULL AS int) AS [C4],
[Extent4].[id] AS [id1],
[Extent4].[id] AS [id2],
[Extent4].[y] AS [y]
FROM [dbo].[OneRowTable] AS [Extent3]
CROSS JOIN [dbo].[b] AS [Extent4]
WHERE [Extent4].[id] < 999) AS [UnionAll1]
ORDER BY [UnionAll1].[x] ASC, [UnionAll1].[C1] ASC
Not exactly the original shape. The translator took another way creating two one row results and using union all to get it into one query. Except this, the query is in general the same (the explicit joins are as result same as the subselects, though little bit more confusing in this case).
Again, this isn’t general purpose way of doing it and may result in worse performance than running queries separately and I would recommend using it only after careful testing and on controlled limited set of queries.
Today I uncovered a magic command from Entity Framework v4 when you create M:N association and the underlying table is defined with both columns as identity and you insert there. I don’t what’s it good for, as this table in fact only stores the two IDs to connect other tables. But somebody may build some logic on identity there, sure.
When I first saw the command, I was completely stunned. I had no idea what’s going on there and whether I see there one or more commands. You can have fun too:
declare @generated_keys table([ID_A] int, [ID_B] int)
insert [dbo].[A_B]
output inserted.[ID_A], inserted.[ID_B] into @generated_keys
default values
select t.[ID_A], t.[ID_B]
from @generated_keys as g join [dbo].[A_B] as t on g.[ID_A] = t.[ID_A] and g.[ID_B] = t.[ID_B]
where @@ROWCOUNT > 0
As an old school guy I was first looking for semicolons and then later tried to decode it by “parsing” the content.
Isn’t it nice…
Today I seen a code with good chance of hard to find mysterious bugs. Let’s start with database table structure we’re going to use for demonstration.
create table NullTest(id int primary key, b bit);
insert into NullTest values (0, 1);
insert into NullTest values (1, 0);
insert into NullTest values (2, null);
If you now try to query this table via LINQ (i.e. LINQ to Entities) you may get surprising results.
foreach (var item in ent.NullTests.Where(x => x.b != true))
{
Console.WriteLine(string.Format("ID: {0} t B: {1}", item.id, item.b));
}
Console.WriteLine("===");
foreach (var item in ent.NullTests.AsEnumerable().Where(x => x.b != true))
{
Console.WriteLine(string.Format("ID: {0} t B: {1}", item.id, item.b));
}
If you run this code, you’ll get different results.
ID: 1 B: False
===
ID: 1 B: False
ID: 2 B:
What happened? Is the database engine doing something wrong? Or is there a bug in LINQ? Neither of those. In fact both results are correct. The second one (evaluated in .NET on client) is obvious why it’s as is. But what happened in processing of first one (evaluated on database side)? The devil is in NULL logic. Every operation with NULL results in NULL or false if it’s a boolean operation. And this exactly explains the inconsistent result. In .NET null != true is true but in databases it’s false (because of the NULL rules described above).
Thus if you’re writing LINQ query for database, although the impedance mismatch should be hidden from you when using LINQ, you need to take into account different NULL handling in database engines and in .NET (or any common programming language).
Remember the DBNull.Value? That was explicit solution for this “problem”.
When I first heard about exposing foreign keys in conceptual model I was getting crazy. It’s the object world, you shouldn’t think this way, in a relational world. On the other hand, working purely in objects can be a pain, especially in web development, and performance problem. Sure, foreign keys can solve you some “problems” (and maybe add some) without tweaking the EntityKey or doing stub entities. Which is hard when dealing with POCO.
But is this a really way to go? Exchange cleanness for comfort.
I don’t know. I was doing the EntityKey magic, and it was magic, because it was not clean. Now I can do it easily, but. For POCO it’s harder, as there’s no EntityKey, but again, you have plain objects – why to deal with foreign keys? What if you move to some non-relational store?
But still one piece is left. The M:N association. Here I cannot use any foreign key, so it’s back to hacking or pure objects. And maybe this is the point. If creating some kind of comfort here for developers, why not to find some way for complete story? Wouldn’t it be nice?
Now I know (see how good is trying to write your own ideas). I don’t like the current concept of FKs. It’s too easy, and just too replicating behavior of relational world. But if there would have been some improvement for the other types of associations to cover all types in uniform way, I would vote for it with both my hands. Although still saying that it’s not nice but acceptable, as relational databases – it seems – will be with us for sure next couple of years.
Next Firebird conference is coming. This year in München, Germany. I’ve never been in München though it’s pretty close to Czech Rep. thus I’m looking forward.
You can find info about conference at firebird-conference.com. I’ll be speaking there too, hence if you’re interested in Firebird and .NET you should definitely come. Every day I have one session. I’ll be covering new (2.5+) protocol implementation in .NET client for Firebird 2.1, Entity Framework support (also new in 2.5) and finally you’ll see how to create Windows phone (formely PocketPC, …) application and accessing Firebird database.
And the conference will be also great place to meet people you know from list etc. and talk face to face about your Firebird related problems, challenges and solutions. If you have any specific need to show (related to my three sessions) feel free to drop line in comments.
I have a strong feeling that MS SQL knows I don’t like it. I don’t say it’s a bad database, but sometimes it’s really “interesting”.
OK, so what I faced this time? Let’s start with basic facts. The NULL value in database is a special value. NULL and NULL is again NULL, NULL and False is again NULL and NULL isn’t equal to NULL. Two days ago I was creating a chain of records in database (which isn’t too relationalish, but …) and I needed unique constraint on one column. No problem you may think. So did I. But not in MS SQL.
Check this example:
1> create table test(id int primary key, foo int);
2> create unique index idx_text on test(foo);
3> go
1> insert into test values (1, null);
2> go
(1 rows affected)
1> insert into test values (2, null);
2> go
Msg 2601, Level 14, State 1, Server X2-001SQLEXPRESS, Line 1 Cannot insert duplicate key row in object 'dbo.test' with unique index 'idx_text '.
The statement has been terminated.
What a mess! Looks like somebody in MS SQL engine team thinks NULL == NULL. After some railing, testing on Firebird and asking my friend about Oracle, I googled: https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=299229. Looks like I’m not alone; feeling better. 
Luckily I’m working on MS SQL 2008 and I can use filtered indices. Created unique index with where clause where <column> is not null and I’m done. But boy that was a bitter finding. Hope I’ll not be punched to the face with these basics again in an at least two months.
I hate transactions, ACID and all the stuff. Really, I do. No, I don’t, it’s a great to have challenges with this kind of thinking. But in last two projects (in a row) I had similar problem and transactions were making it even more challenging.
The simple version is that I needed to have data constraint in database (did I mention that I’m constraint freak?) based on not the row itself, but the data in the table and related tables. If you’ve play with transactions you know this is a problem. Either you may run in read uncommitted mode, see everything and if somebody will do something violating the constraint, even if it will be rolled back, you will start screaming and throwing exceptions or you will use serializable and, to be sure, explicit locking in every piece of trigger or stored procedure code, which is good for you but not for performance. Choose whatever fits your needs better, but right now, for this particular scenario I wish the transactions gone and pretending there’s no isolation from others at all (and with decent performance too).
I know it’s impossible, because interactions in database are making creating some general purpose “command/constraint” tough. And what’s good for one case is definitely not suitable for other.
Anyway maybe with more work done on distributed systems and clouds, where even the simple constraints are interesting to enforce, we’ll find some good way how to solve this.
When you write huge (I mean really huge, not a ~300 lines baby) complex query you may experience, that the generated query looks (well) suboptimal. The reason is that after some line the Entity Framework will gave up on optimization and simply throws it as is. To turn this off and force to simplify it whatever query it is you can add this into your app.config, as Kati Iceva pointed in MSDN forums.
<system.diagnostics>
<switches>
<add name="System.Data.EntityClient.IgnoreOptimizationLimit" value="1" />
</switches>
</system.diagnostics>
But also take into account that this may end up with a significant time spent in EF’s code and at the end the query will be still too big for the store to run it or the store would do better job optimize it. Thus the overall time may be same or even worse (= use carefully).
It’s also worth, if you’re able to write the query a lot simpler, to discuss this in MSDN forums, so the code in EF can be improved.
Julie Lerman made a great post about The cost of eager loading in Entity Framework. And everything there is true, in fact if you take my Entity Framework training, you will know that with all reasons and you’ll also learn performace improvements you may incorporate into your solution.
I want to make some small addition to this post. There’s another stuff to think about. That’s the cost of processing query on server.
You should always consider the cost of parsing, compiling, finding execution plan etc. the query on server as well as fetching the intermediate data (which may cause cleaning up caches etc.). Thus sometimes (and we’re back to balance as Julie said) it’s better to issue couple of smaller (not so complex) queries, rather than one huge query.
If you want to map stored procedure you have three options what the stored procedure can return. Nothing, some scalar value and entity. The problem is that sometimes you have SP that’s returning some data, but not some entity. The way to solve this is to create entity with same shape as the SP is returning. But the problem is, that this entity type needs to be mapped to something, probably table. Else the model is not valid. The good message is, that you can create fake table in SSDL and use it.
But it’s a pain to create it, because you have to deal with XML directly and create not only the fake table with proper structure, but also entity set. When reading pre-prelease
version of Julie Lerman‘s wonderful book Programming Entity Framework there was a sigh about some tool to automate the process. Well today I have some time, to create rough tool to create some kind of this tool.
static void Main(string[] args)
{
#region Initial checking
if (args.Length != 3)
return;
string tablenameToFake = args[0];
string emdxFile = args[1];
string fileForSaving = args[2];
if (!File.Exists(emdxFile))
return;
if (File.Exists(fileForSaving))
return;
#endregion
XDocument xdoc = XDocument.Load(emdxFile);
const string CSDLNamespace = "http://schemas.microsoft.com/ado/2006/04/edm";
const string SSDLNamespace = "http://schemas.microsoft.com/ado/2006/04/edm/ssdl";
XElement csdl = xdoc.Descendants(XName.Get("Schema", CSDLNamespace)).First();
XElement ssdl = xdoc.Descendants(XName.Get("Schema", SSDLNamespace)).First();
XElement csdlItem = csdl.Elements(XName.Get("EntityType", CSDLNamespace))
.Where(x => x.Attribute("Name").Value.ToUpperInvariant() == tablenameToFake.ToUpperInvariant()).FirstOrDefault();
if (csdlItem == null)
return;
Func<string, string> getStoreType = (string csdlTypeName) =>
{
// Use some information from store provider or use some dummy or extend this switch using common SQL names?
switch (csdlTypeName)
{
case "Int16":
case "Int32":
case "Int64":
return "int";
case "String":
return "varchar";
default:
return "blob";
}
};
#region New EntityType creation
XNamespace n = SSDLNamespace;
XElement tableToFake = new XElement(n + "EntityType", new XAttribute("Name", tablenameToFake));
var keys = from x in csdlItem.Element(XName.Get("Key", CSDLNamespace)).Elements(XName.Get("PropertyRef", CSDLNamespace))
select new XElement(n + "PropertyRef",
new XAttribute("Name", x.Attribute("Name").Value));
tableToFake.Add(new XElement(n + "Key", keys.ToArray()));
var columns = from x in csdlItem.Elements(XName.Get("Property", CSDLNamespace))
select new XElement(n + "Property",
new[] {
new XAttribute("Name", x.Attribute("Name").Value),
new XAttribute("Type", getStoreType(x.Attribute("Type").Value)),
new XAttribute("Nullable", (x.Attribute("Nullable") != null ? x.Attribute("Nullable").Value : "true"))
});
tableToFake.Add(columns.ToArray());
#endregion
#region EntitySet for new entity
XElement someEntitySet = ssdl.Element(XName.Get("EntityContainer", SSDLNamespace)).Element(XName.Get("EntitySet", SSDLNamespace));
XElement newEntitySet = new XElement(someEntitySet);
newEntitySet.Attribute("Name").Value = tablenameToFake;
newEntitySet.Attribute("EntityType").Value = ssdl.Attribute("Namespace").Value + "." + tablenameToFake;
#endregion
ssdl.Add(tableToFake);
ssdl.Element(XName.Get("EntityContainer", SSDLNamespace)).Add(newEntitySet);
using (XmlTextWriter writer = new XmlTextWriter(fileForSaving, Encoding.Default))
{
xdoc.WriteTo(writer);
}
}
This code simply looks for entity you specified and makes the appropriate items in SSDL. It’s very rough, especially datatypes for table are scamped
, but you can extend it youself with your favourites. Or maybe better use some information from store provider. Anyway the basic idea is here, if you extend dataypes, it will work well for this stuff. Mapping should be done by you in designer, although because column names are same as entity’s, you only need to choose right table name, rest will be done by the designer. And of course, when updating model from database, these changes are lost.
Comments are welcome.
I’m pleased to announce 2.5.0 Beta 1 for .NET 3.5/2.0 [with Entity
Framework support] version. It contains several bugfixes as well as
brand new Entity Framework support (still beta!). Looking forward to
your feedback.
Binary as well as sources can be downloaded from
http://www.firebirdsql.org/index.php?op=files&id=netprovider.
Today there was a question in db section in builder.cz forum. In essence, how to show people having birthday today or in couple of days if I have a birthdate. Well the solution I’ll show you here is in Firebird syntax, but shouldn’t be a problem to rewrite it to any other platform you like.
So the solution is like this (of course, you can find many other ways how to solve it):
select dateadd(year, datediff(year, birthdate, current_date), birthdate) from
(
select cast('1.2.1993' as date) as birthdate from rdb$database
);
OK, what’s the idea behind. First step is to get difference between these dates in year. Then, using the dateadd function to prevent some mismatch in date arithmetics (i.e. leap years), to add this difference to birthdate. Now you have it in “current year”, so it’s easy to test whether it’s between today and today + x. To improve speed, you can create computed index for this expression.