Are there any rapid Database protoyping tools that don't require me to declare a database schema, but rather create it based on the way I'm using my entities.
For example, assuming an empty database (pseudo code):
user1 = new User() // Creates the user table with a single id column
user1.firstName = "Allain" // alters the table to have a firstName column as varchar(255)
user2 = new User() // Reuses the table
user2.firstName = "Bob"
user2.lastName = "Loblaw" // Alters the table to have a last name column
Since there are logical assumptions that can be made when dynamically creating the schema, and you could always override its choices by using your DB tools to tweak it later.
Also, you could generate your schema by unit testing it this way.
And obviously this is only for prototyping.
Is there anything like this out there?
Google's Application Engine works like this. When you download the toolkit you get a local copy of the database engine for testing.
Grails uses Hibernate to persist domain objects and produces behavior similar to what you describe. To alter the schema you simply modify the domain, in this simple case the file is named User.groovy.
class User {
String userName
String firstName
String lastName
Date dateCreated
Date lastUpdated
static constraints = {
userName(blank: false, unique: true)
firstName(blank: false)
lastName(blank: false)
}
String toString() {"$lastName, $firstName"}
}
Saving the file alters the schema automatically. Likewise, if you are using scaffolding it is updated. The prototype process becomes run the application, view the page in your browser, modify the domain, refresh the browser, and see the changes.
I agree with the NHibernate approach and auto-database-generation. But, if you want to avoid writing a configuration file, and stay close to the code, use Castle's ActiveRecord. You declare the 'schema' directly on the class with via attributes.
[ActiveRecord]
public class User : ActiveRecordBase<User>
{
[PrimaryKey]
public Int32 UserId { get; set; }
[Property]
public String FirstName { get; set; }
}
There are a variety of constraints you can apply (validation, bounds, etc) and you can declare relationships between different data model classes. Most of these options are parameters added to the attributes. It's rather simple.
So, you're working with code. Declaring usage in code. And when you're done, let ActiveRecord create the database.
ActiveRecordStarter.Initialize();
ActiveRecordStarter.CreateSchema();
May be not exactly responding to your general question, but if you used (N)Hibernate then you can automatically generate the database schema from your hbm mapping files.
Its not done directly from your code as you seem to be wanting but Hibernate Schema generation seems to work well for us
Do you want the schema, but have it generated, or do you actually want NO schema?
For the former I'd go with nhibernate as #tom-carter said. Have it generate your schema for you, and you are all good (atleast until you roll your app out, then look at something like Tarantino and RedGate SQL Diff or whatever it's called to generate update scripts)
If you want the latter.... google app engine does this, as I've discovered this afternoon, and it's very nice. If you want to stick with code under your control, I'd suggest looking at CouchDB, tho it's a bit of upfront work getting it setup. But once you have it, it's a totally, 100% schema-free database. Well, you have an ID and a Version, but thats it - the rest is up to you. http://incubator.apache.org/couchdb/
But by the sounds of it (N)hibernate would suite the best, but I could be wrong.
You could use an object database.
Related
Is there a way to use multimapping in Dapper in a generic way, without using custom SQL embedded in C# code?
See for example
Correct use of Multimapping in Dapper
Is there a generic way to query the data from 2 related entities, where common fields are determined automatically for join?
Don't do this. Don't even think this way! Databases are long lasting and normalized. Objects are perishable and frequently denormalized, and transitioning between the two is something to do thoughtfully, when you're writing your SQL. This is really not a step to automate. Long, painful experience has convinced many of us that database abstractions (tables and joins) should not just be sucked into (or generated out of) code. If you're not yet convinced, then use an established ORM.
If, on the other hand, you absolutely want to be in control of your SQL, but its the "embedding" in string literals in C# that bugs you, then I couldn't agree more. Can I suggest QueryFirst, a visual studio extension that generates the C# wrapper for your queries. Your SQL stays in a real SQL file, syntax validated, DB references checked, and at each save, QueryFirst generates a wrapper class with Execute() methods, and a POCO for the results.
By multi-mapping, I presume you want to fill a graph of nested objects. A nice way to do this is to use one QueryFirst .sql per class in your graph, then in the partial class of the parent, add a List of children. (QueryFirst generated POCOs are split across 2 partial classes, you control one of them, the tool generates the other.)
So, for a graph of Customers and their orders...
In the parent sql
select * from customers where name like #custName
The child sql
select * from orders where customerId = #customerId
In the parent partial class, for eager loading...
public List<Orders> orders;
public void OnLoad()
{
orders = new getOrders().Execute(customerId); // property of the parent POCO
}
or for lazy loading...
private List<Orders> _orders;
public List<Orders> orders
{
get
{
return _orders ?? _orders = new GetOrders().Execute(customerId);
}
}
5 lines of code, not counting brackets, and you have a nested graph, lazy loaded or eager loaded as you prefer, the interface discoverable in code (intellisense for the input parameter and result). Their might be hundreds of columns in those tables, whose names you will never need to re-type, and whose datatypes are going to flow transparently into your C#.
Clean separation of responsibilities. Total control. Disclaimer : I wrote QueryFirst :-)
Multimapping with Dapper is a method of running multiple SQL queries at once and then return each result mapped to a specific object.
In the context of this question, Multimapping is not even relevant, re: you're asking for a way to automatically generate a SQL query from the given objects and creating the correct joins which would result in a single SQL query which is not related to Multimapping.
I suspect what you're looking for is something along the lines of the Entity Framework. There are a couple of Dapper extension projects you may want to look into which will generate some of your SQL. See: Dapper.Rainbow VS Dapper.Contrib
Yesterday I asked this question about changing the name of the __Migration History table generated by Entity Framework when using a Code First approach. The provided link was helpful in saying how to do what we want (and by "want" I mean what we're being forced into by our DBAs), however also left a somewhat non-specific and dire-sounding warning that says,
Words of precaution
Changing the migration history table is powerful but you need to be
careful to not overdo it. EF runtime currently does not check whether
the customized migrations history table is compatible with the
runtime. If it is not your application may break at runtime or behave
in unpredictable ways. This is even more important if you use multiple
contexts per database in which case multiple contexts can use the same
migration history table to store information about migrations.
We tried to use this warning to reason with the DBA team, telling them that we shouldn't mess with things because "here be dragons". Their response was, "It sounds more like the danger is in changing the content or the table structure, not the name. Go ahead and try it and see what happens."
Has anyone here changed the name of the __Migrations History table, and what was the result? Is it dangerous?
Changing the name of the migrations history table is possible.
But you have to tell EF this by calling the HasDefaultSchema method with the name of the schema in the OnModelCreating method of your DbContext class:
public partial class CustomerDatabasesModel : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("CustomerDatabases");
// Fluent API configuration
}
}
This the will cause EF to create a "CustomerDatabases" prefix for all database tables.
So in this example "CustomerDatabases" replaces the standard of "dbo" prefix of your tables. Your migration history table will be have the name CustomerDatabases.__MigrationHistory.
So in fact, you change the owner name of the database (the first part), the second part "__MigrationHistory" stays the same.
Usage scenario:
You usually do this, if you work with more than one DbContext.
So you can have more than one MigrationHistory table in a single database, one for each context.
Of cause you should carefully test this and perform database backups before.
Please check out this answer too:
Entity-Framework: On Database, multiple DbContexts
We have a Grails project that needs to pull data from a SQL Server 2008 view. We just need to do a basic select from the view.
Is there a config setting for views such that we can map a domain class to the view?
Or should we use raw SQL like:
db.rows("SELECT foo, bar FROM my_view")
You can use SQL, e.g. with groovy.sql.Sql as suggested in the other similar question's answer, but it's also possible in a domain class. If you create a domain class (use any sensible name) and specify its table name as the name of the view, you can select from it. You'll have problems creating and updating of course, but if you only want to read then it'll be fine:
class SomeDomainClass {
String foo
Integer bar
static mapping = {
table 'my_view'
}
}
If you name the class MyView then mapping isn't needed since the naming convention applies, but this would be a bad name for the class since using it isn't related to the fact that it's backed by a view.
Note that you'll also have problems when using dbCreate set to "create", "create-drop", or "update" since Hibernate will try to create the table, but it shouldn't cause any real problem and just display an ignorable error like "could not create table 'my_view' since it already exists". And once you move to using database migrations this won't be a problem at all.
I was making an internet MVC 4 application in Visual Studio 2012 and I wanted to add users using SingleMembership. At first I saw that the users database was not exactly where I wanted them to be, they were on a SQL/Express database and I want them on a SQL/Server I have already created for all the models in my application. So what I did is modify the connection string created by Visual Studio 2012 for my database which was:
<add name="Test2_Entities" connectionString="metadata=res://*/Models.Model.csdl|res://*/Models.Model.ssdl|res://*/Models.Model.msl;provider=System.Data.SqlClient;provider connection string="data source=FERNANDO-PC\SQLSERVER;initial catalog=Test2;persist security info=True;user id=****;password=****;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
and then I realized I needed 2 connection strings because the metadata part was giving some errors and the provider name change it to "System.Data.SqlClient", so the new connection string is really the first one but with this changes:
<add name="Test2_Entities2" connectionString="data source=FERNANDO-PC\SQLSERVER;initial catalog=Test2;persist security info=True;user id=****;password=****;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
In otder to have the users tables created in my database, I also changed a line in the InitializeSingleMemebershipAttribute.cs file in the Filters folder (to be precise, the line 41) from:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
to:
WebSecurity.InitializeDatabaseConnection("Test2_Entities2", "UserProfile", "UserId", "UserName", autoCreateTables: true);
and other line in the AccountModels.cs which is in the Models folder from:
public UsersContext() : base("DefaultConnection")
to:
public UsersContext() : base("Test2_Entities")
Whit that the default tables which control the memberships, roles, OAuth and those things, are created in the database I want.
(This is the background of the problem, and thought that some people would find it helpful)
The problem is that when the tables are created in my SQL database, there are columns that are not in the datatypes I defined in the AccountModels.cs and the additional fields are not created. More specifically, in the AccountModels.cs I have this class:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Guid UserId { get; set; }
public string UserName { get; set; }
public string RandomString { get; set; }
}
and in the tables created, the UserID gets an int which when I try to change in I get an error:
Conversion from 'int' to 'uniqueidentifier' is not supported on the
connected database server.
and also, the RandomString string does not appear on the UserProfiles table.
The answer to this question:
"How do I manage profiles using SingleMembership" stackoverflow question
is really helpful, but I can't change the fields and datatypes like the answer proposes.
Is there something I'm missing? or something I should set before doing this changes?
You cannot change the UserId type because it is used as a foreign key to other tables that are also generated in this database. If you successfully get it to change this column in the database you will get the following error:
UserProfile.UserId' is not the same data type as referencing column 'webpages_UsersInRoles.UserId' in foreign key 'fk_UserId'
When I tried this some of the tables were created and as you can see other tables use the UserId to link to the UserProfile table.
But as you can also see from this snapshot I was able to add the custom column called RandomString. I was baffled by your comment that you could not change the UserProfile object and have it reflected in the table. I have seen numerous complaints about this on this site so I tried messing around with making changes to see if I could reproduce the problem. When I was working with this example and I was able to change UserId back to an int so that it would work and even add another property/column. It also worked as you can see in this snaphsot.
But then I opened an older project that had a custom UserProfile and tried modifying it and it would not reflect the changes in the database. It was stuck with the last model I had used (a custom model that differed from the one generated by the MVC 4 template) and would not change even if I deleted the database or modified the database name. This MVC 4 template uses EF 5 and I think it has to do with how database migration was handled in that version and the unconventional way that InitializeSimpleMembershipAttribute creates the database as seen in this code snippet:
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
To make a long story short, I have seen these MVC 4 projects get into this state where changes to the UserProfile will not work and I have not figured out a solution to the problem yet. I will update this answer if I find a solution.
Just remove the GUID part from your code (let the default UserID remain the primary key) and it will work. Kevin Junghans has explained why.
Running your MvcApplication should now make the necessary alteration to the Table Structure.
In case it doesn't:
You'll have to do a migration.
or
You could just drop the UserProfile (and the other webpages_* tables) from the database and then Run the Application
This may help you with the migration process
Let's say you have a table containing articles and you want want to display a list of them, excluding the actual article text. When you get a list of the article objects using LINQ or the Entity Framework, is there a LOT of overhead associated with getting that text column too? I assume that when you start enumerating the list, the article text will be stored in memory until the objects are disposed of.
So would it make sense to create an intermediary object that doesn't contain the text column? If so, how would you do this? Make a class inside your DAL, allow the ORM to automatically create one by setting up a stored procedure, or some other process?
The overhead isn't huge (just the cost of sending the data over the wire), but if you don't need the data sure, don't return it. I find the easiest way is to use anonymous types:
from a in Context.Articles
select new {Name = a.Name, Author = a.Author};
Since you're not actually materializing any Article instances, the Entity Framework won't need to fill out all the properties of an instance.
If you don't need the data you should definitely create a different type. By convention I typically name this sort of class "nnnInfo" or "nnnListItem". To create ArticleListItem, in L2S, simply drag the table to your DataContext designer a second time. Then rename it from 'Article1' to 'ArticleListItem' and remove the unneeded properties (rt click, delete). In EF, the process would be similar. As Craig notes, you could use anonymous types, but by creating a concrete type, you can reuse throughout your app, expose via services, etc.
A second way to do this would be to create the class manually and write an extension method to return ArticleListItem:
public static IQueryable<ArticleListItem> ToListItems(this IQueryable<Article> articles)
{
return from a in articles select new ArticleListItem{ Title = a.Title, ...}
}
This would allow you to "cast" any queries against Article as ArticleListItem...