This may be a bit silly, but all the applications I've built have always utilized the EF Code-First approach to generate the database. When using this method, I've always accessed the database through the Context:
public class RandomController : Controller
{
public CombosContext db = new CombosContext();
//
// GET: /Home/
public ActionResult Index()
{
var rows = db.Combos.OrderBy(a => a.Id).ToList();
However, what if the database is already created for me, OR I create one by adding entities to the schema/design surface and then generate the database from that. How would I access the db without the
public CombosContext db = new ComboxContext();
If the DB is already created, you can use the Database First approuch: http://blogs.msdn.com/b/adonet/archive/2011/09/28/ef-4-2-model-amp-database-first-walkthrough.aspx
A basic setup would by to rightclick the project in the solution explorer and click Add > new item. On the dialog, select Data on the left pane and ADO.net Entity Data Model and follow the wizard to create your model based on the database. This way, you will have a context object exactly the way you have with code first (with some minor changes, but works almost the same).
You can still do this with Code first and is the better approach IMHO. Use the Entity Framework Power Tools to reverse engineer your existing database into a code-first model.
http://visualstudiogallery.msdn.microsoft.com/72a60b14-1581-4b9b-89f2-846072eff19d/
See my demo on using it at:
http://channel9.msdn.com/Events/TechEd/NorthAmerica/2012/DEV215
Related
I'm creating a web app based on a database. The datas in the database need to be displayed, edited and deleted by the web app user.
Right now I need to remove elements in my sqlite database table after the user inputs the name of the database table and the id (which is also the primary key) of the element. How can I do it?
I always used Entity Framework before and also in the Web App so I was looking for a solution with it, but if there's a simpler way to do it, I'll stick with it.
Thank you
I think the answer here is similar but I need help to adapt it to what I need now.
Entity Framework C# queries from strings
this is the UI
and here is the endpoint in the backend
//DELETE method
[HttpDelete("DeleteElementInTable")]
public IActionResult DeleteElementInTable(string tableName, string elementKey) //url query parameters
{
var db = new MyContext();
//code to remove the item ... something like:
DbManager.RemoveElement(tableName, elementKey); //DbManager is the static class dealing with the db context
return //csv of the deleted element;
}
I'm still a young developer but here I can see there are some lacks of knowledge. First of all, which technology are you using to build your web-app? From what you posted my guess is you are trying to use MVC. As #Panagiotis Kanavos said above you need an entity to interact with the database if you want to use Entity Framework, through which you don't need to pass table name in your GET function. Last but not less important you can't execute the delete operation in a GET function.
How do you use unit/integration testing to ensure that a code-first migration works correctly on a populated previous-version database, including any additional code to map data from one column or table to another?
I found some previous answers that used classes in the System.Data.Entity namespace, but it appears these have become obsolete with Entity Framework Core and manual control of migrations is not possible?
I found a solution for myself which I will post, but I welcome other, better solutions.
The database is defined by a Context class, and ContextModelSnapshot class, a series of migration files, and the C# objects that the data tables store.
If you haven't created the migration yet, copy all of these files to your test project and rename the classes all with a suffix, e.g. "MyDataEntity" => "MyDataEntityVersion1". Edit the bundled .Design.cs files accordingly. Afterwards, create the new migration on the original.
If you have created the new migration but can't step back, you can manually edit the ContextModelSnapshot file to revert the changes.
The key to this working is that both point to the same database file. One expects the original state, and the other expects the upgraded state.
In your test case, you can then do:
[TestInitialize]
public void TestInit()
{
using (var db = new MyDataContext())
db.Database.EnsureDeleted(); // reset database before each test
}
[TestMethod]
public void Migrate_Version1_To_Version2_On_Populated_Database()
{
using (var db = new MyDataContextVersion1())
db.Database.Migrate(); // create database and apply migrations up through Version 1
// populate the Version 1 database
App.InitializeDatabase(); // whatever method you would normally call to read/update the database
// assert statements to test that the Version 2 database looks like you expect.
}
where InitializeDatabase() looks something like:
public void InitializeDatabase()
{
using (var db = new MyDataContext())
{
db.Database.Migrate();
// detect if upgrade needed and set new columns
db.SaveChanges();
}
}
Note that this solution is in part motivated by using SQLite, which does not support dropping columns in a migration. It discouraged me from trying to do anything more fancy inside the migrations.
I need to map to a view when using EF6 with migrations.
The view pivots 2 other tables to enable a simple summary view of the underlying data, the idea being it allows us to use this in a summary index view.
The issue I have is I am unable create a migration that either deploys the view (ideal goal) or deploys the DB without the view for later manual deployment.
In most attempts, following other SO questions, I end up either deadlocking the Add-Migration and Update-Database commands or generally causing an error that breaks one or the other.
What is the current best way to use EF6 to access views, even if I lose the ability to automatically deploy them with the migrations, and not cause errors with migrations.
Further detail
The Db contains 2 tables Reports and ReportAnswers. The view ReportView combines these two and pivots ReportAnswers to allow some of the rows to become columns in this summary view.
Reports and ReportAnswers were depolied via EF Migrations. The view is currently a script that needs be added to the deployment somehow.
Reports, ReportAnswers & ReportView are accessible from the db Context
public virtual DbSet<ReportAnswer> ReportAnswers { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<ReportView> ReportView { get; set; }
I have tried using Add-Migration Name -IgnoreChanges to create a blank migration and then manually adding the view to the Up() and Down() methods but this just deadlocks the migration and update commands, each wanting the other to run first.
I have also tried using modelBuilder.Ignore<ReportView>(); to ignore the type when running the migrations but this proved incredibly error prone, even though it did seem to work at least once.
I just walked around interesting article about using views with EF Core few days ago, but I found also the very same using EF 6.
You may want to use Seed method instead of migration Up and Down methods.
protected override void Seed({DbContextType} context)
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
var baseDir = Path.GetDirectoryName(path) + "\\Migrations\\{CreateViewSQLScriptFilename}.sql";
context.Database.ExecuteSqlCommand(File.ReadAllText(baseDir));
}
Your SQL command should look like sample below.
IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[{ViewName}]'))
EXEC dbo.sp_executesql #statement = N'CREATE VIEW [dbo].[{ViewName}]
AS
SELECT {SelectCommand}
It is not perfect, but I hope at least helpful.
I found another blog post about this topic and the writer says to use Sql(#"CREATE VIEW dbo.{ViewName} AS...") in Up method and Sql(#"DROP VIEW dbo.{ViewName};") in Down method. I added it as you didn't supplied the code from Up and Down migration methods. Maybe good idea will be to add SqlFile instead of Sql method.
There is also option to create customized code or sql generator and plug it in to migrations, but I guess it is not the things you are looking for.
Let me know in comment in case you need additional help.
Related links:
Using Views with Entity Framework Code First
EF CODE FIRST - VIEWS AND STORED PROCEDURES
Leveraging Views in Entity Framework
DbMigration.Sql Method (String, Boolean, Object)
DbMigration.SqlFile Method (String, Boolean, Object)
I came across this related question: How can I generate DDL scripts from Entity Framework 4.3 Code-First Model?
But this doesn't appear to answer the question of when a Code First application actually checks the existence/correctness of the DB and modifies it if necessary. Is it at run-time or build time? Assuming it's at run-time is it at start-up or when you create the DbContext or at the last possible moment e.g. when you try to write/read the DB table(s) it checks they exist on a case-by-case basis?
It is ceated at rutime the first time you access an entity, ie,
using (var db = new MyDBContext())
{
var items = db.MyObj.Count() // <- Here it is created!
}
There are some flavors on how, like if you set the creating strategy to CreateDatabaseIfNotExists, DropCreateDatabaseAlways, Etc. Please give this a look:
http://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx
The column Model in the table __MigrationHistory is serialized and gzipped(base64) version of your EDMX. In code first the column Model is generated by Add-Migration and stored in the second part of the migration partial class and in the database when the database is created as binary stream varbinary(max).
When the database initializer (Database.SetInitializer) is called, then EF generate from the classes on the fly(Runtime) the current Entity Data Model(EDMX). The generated model will be serialized, zipped(base64) and finally compare it with the stored Model of the migration history table.
The comparison happens before the DbContext is created and, if the two Models(binary streams) are not identical then you will get a compatibility exception.
As I've mentioned in a couple other questions, I'm currently trying to replace a home-grown ORM with the Entity Framework, now that our database can support it.
Currently, we have certain objects set up such that they are mapped to a table in our internal database and a table in the database that runs our website (which is not even in the same state, let alone on the same server). So, for example:
Part p = new Part(12345);
p.Name = "Renamed part";
p.Update();
will update both the internal and the web databases simultaneously to reflect that the part with ID 12345 is now named "Renamed part". This logic only needs to go one direction (internal -> web) for the time being. We access the web database through a LINQ-to-SQL DBML and its objects.
I think my question has two parts, although it's possible I'm not asking the right question in the first place.
Is there any kind of "OnUpdate()" event/method that I can use to trigger validation of "Should this be pushed to the web?" and then do the pushing? If there isn't anything by default, is there any other way I can insert logic between .SaveChanges() and when it hits the database?
Is there any way that I can specify for each object which DBML object it maps to, and for each EF auto-generated property which property on the L2S object to map to? The names often match up, but not always so I can't rely on that. Alternatively, can I modify the L2S objects in a generic way so that they can populate themselves from the EF object?
Sounds like a job for Sql Server replication.
You don't need to inter-connect the two together as it seems you're saying with question 2.
Just have the two separate databases with their own EF or L2S models and abstract them away using repositories with domain objects.
This is the solution I ended up going with. Note that the implementation of IAdvantageWebTable is inherited from the existing base class, so nothing special needed to be done for EF-based classes, once the T4 template was modified to inherit correctly.
public partial class EntityContext
{
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
var modified = this.ObjectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added); // Get the list of things to update
var result = base.SaveChanges(options); // Call the base SaveChanges, which clears that list.
using (var context = new WebDataContext()) // This is the second database context.
{
foreach (var obj in modified)
{
var table = obj.Entity as IAdvantageWebTable;
if (table != null)
{
table.UpdateWeb(context); // This is IAdvantageWebTable.UpdateWeb(), which calls all the existing logic I've had in place for years.
}
}
context.SubmitChanges();
}
return result;
}
}