WCF project trying to recreate database when it exists already - c#

So I am attempting to utilize EF and my existing database in a WCF project in order to add some entities to the database.
Setup:
So I have several layers to my solution.
Core (class library)
Data (class library)
Services (class library)
WCFServices(WCF application)
WebUI (MVC project)
Entity framework 6.2.0 is installed in my Data, WCFServices, and WebUI project. (picture below).
So my database models are stored in the core project and my migrations for the database are stored in the data project. My web UI project has no issues accessing the database and using it. I have the exact same connection strings stored in both the MVC project and the WCF project.
MVC web.config connection string
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-SQDCDashboard.WebUI-20190610100239.mdf;user id = exampleUser; password = ExamplePassword;Integrated Security=False" providerName="System.Data.SqlClient" />
The WCF project has the following connection string.
WCF web.config connection string
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-SQDCDashboard.WebUI-20190610100239.mdf;user id = exampleUser; password = ExamplePassword;Integrated Security=False" providerName="System.Data.SqlClient" />
As you can see they both match exactly.
WCF service
public class OrderService : IOrderService
{
public string InsertOrder(OrderDTO order)
{
try
{
using (var context = new DataContext())
{
var productionLine = context.ProductionLines
.Where(x => x.ComputerName == order.ComputerName)
.FirstOrDefault();
if (productionLine == null)
throw new Exception("Production line could not be determined from computer name");
context.Orders.Add(new Core.Models.Order
{
MaterialNumber = order.MaterialNumber,
SerialNumber = order.SerialNumber,
ProductionNumber = order.ProductionNumber,
SalesNumber = order.SalesNumber,
OrderComplete = false,
ProductionLineId = productionLine.Id
});
context.SaveChanges();
return "Success";
}
}
catch (Exception ex)
{
return ex.Message;
}
}
}
The Error
So here is where the issue comes in. When I run the WCF test client to test my service, it throws the following error:
Cannot create file 'C:\Users\eric_obermuller\Source\Repos\SQDC Dashboard\SQDCDashboard\SQDCDashboard.WCFServices\App_Data\aspnet-SQDCDashboard.WebUI-20190610100239.mdf' because it already exists. Change the file path or the file name, and retry the operation.
CREATE DATABASE failed. Some file names listed could not be created. Check related errors.
This really confuses me because the database already exists. Why is it trying to create a new one? I am a bit of a beginner when it comes to structuring multiple projects in a single solution. So it could possibly be I just don't understand how EF is interacting between the projects?
I did notice that both my WCF project and my MVC project have their own database files in their respective App_Data folders. I have to say I am not sure how EF uses these files in conjunction with the actual local db, it has always sort of confused me so I may be missing something here (see below).
What I have tried
Originally I was using windows authentication but tried switching to SQL Server authentication (which is what I will end up using later).
I tried deleting the migrations folder in my project and dropped the database migrations table. I re-enabled migrations, added an empty migration, and updated the database.
I triple checked that the SQL Server account I am referencing has read/write permissions to the database.
Final Remarks
Again, I have 0 issues using the database within my actual MVC web UI project. My MVC project does use ninject to inject dependencies from my Service project into the controllers, it also injects the dbContext (stored in my data project) into some generic repositories (also stored in my data project), which are used in my Services class library project.
My WCF project does NOT use ninject in any manner, I am directly referencing the dbcontext, as this service is a very simple one and has no need for all that. So I could also see this being the possible issue?

Which DatabaseInitializer you have setup for DB migrations? if you are using 'DropCreateDatabaseAlways' initializer and have same database for two application running in parallel then that might be causing the problem.
While your MVC app is running fine, but WCF will fail while booting up the DBContext as it will try to drop and recreate the Database.
Change your database initializers to the one that would fit this scenario. "DropAndRecreateAlways/ModelChange" are not best candidates.

Related

Entity Framework creates a database with a wrong name

I have two projects in my solution:
An ASP.NET Web API project with EF
A console app with EF
Both projects are configured to connect to SQL Server and have the same connection string defined in the app/web.config:
<add name="AppContext"
providerName="System.Data.SqlClient"
connectionString="Data Source=localhost\SQLEXPRESS;Database=XYZAC;Integrated Security=True" />
The problem only occurs with the console app. The web app creates the XYZAC database correctly. The console app, however, creates a database with the name along the lines of Namespace.AppContext, which isn't at all what I need. Because of that there is no communication between these projects.
I tried changing Database= to Initial Catalog= in the connection string of the console app, but it didn't change anything.
What can be the cause of this? Can this be happening because the API is logging in via IIS APPPOOL\XYZAC user and the app via WINSRV\Administrator? Seems unlikely, because both have pretty much the same permission groups and access to everything, but I'm not sure what else can be the cause.
What am I doing wrong here?
Edit: I'm sharing the DB models between these two projects. I'll try hard-coding the connection string into the constructor.
Try scaffolding from created xyz database to the console application and see if it connects with the scaffolded context .
Hard-coding the same string like this solved the problem:
public AppContext() : base("Sql n stuff;XYZAC")
Cool. As long as it works, right?

AutomaticDataLossException thrown after initial migration runs in EF 6 in SQL Server but not MySQL

Background info:
I am about to start a new project written in C# (vs2015) which will be using Entity Framework 6 within its DAL. One of the core requirements is that the system must be able to run against either SQL Server, Azure SQL server, MySQL or Oracle as chosen by the user simply changing the connection string in the web.config.
So prior to the project kick-off I am trying to get more familiar with Entity Framework as I have not used it outside of a few tutorials before.
I have written a small proof of concept app, the purpose of which is to determine how I can use EF to quickly swap a web api to use a different underlying DB. For the PoC I am using SQL Server express v12 and MySQL v5.6, C#, Entity Framework 6 via a code first approach.
I have hit a road block with my PoC, I am seeing different behaviour when running against MySQL compared to when I am running against SQL Server. I am using the following EF context:
<context type="POC.Core.Api.DataAccessLayer.SchoolContext, POC.Core.Api" disableDatabaseInitialization="false">
<databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[POC.Core.Api.DataAccessLayer.SchoolContext, POC.Core.Api], [POC.Core.Api.Migrations.Configuration, POC.Core.Api]], EntityFramework"></databaseInitializer>
</context>
I have two migration scripts, one which is the initial creation and another which just adds a property to an object.
I have some test data being created in the seed method in the configuration class which looks like this (:
public Configuration()
{
AutomaticMigrationsEnabled = true;
this.SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
}
protected override void Seed(WeldOffice.Core.Api.DataAccessLayer.SchoolContext context)
{
var students = new List<Student>
{
new Student { FirstMidName = "Carson", LastName = "Alexander",
EnrollmentDate = DateTime.Parse("2010-09-01") },
...
};
Both my MySQL and SQL servers do not yet have the database present at all yet.
As I want the user to be able to specify the DB I am relying on in-code methods to create the DB structure etc.
Given this scenario, my understanding is that the following occurs when the db context is first hit when running the app:
Check for existence of the database - it is not present so it will be created.
Check if the initial creation script has been run - it has not so run it.
Check if the add property script has been run - it has not so run it.
Run the seed method to ensure data is present and correct.
In MySQL this all works as expected, the database is created, the tables set up and the data populated. The two migration scripts are listed in the migration table.
In SQL Server, steps 1,2,3 all work and the database is created and the tables set up. The two migration scripts are listed in the migration table. However, step 4 is not run, the Seed method is never hit and instead a AutomaticDataLossException exception is thrown.
If I set AutomaticMigrationDataLossAllowed = true then step 4 also works and everything is as expected. But, I would not really want to have AutomaticMigrationDataLossAllowed set to true and don't see why this is necessary in SQL server but not MySQL. Why is this the case? I feel I am missing something fundamental.
Please keep in mind this is just a proof on concept, in production there will be no seed data anyway, and I would rather a dba create the db via sql scripts etc.

No connection string found in App config using external Start-up application

I am creating a dll project in C# using Visual Studio 2013 .Net 4.5. The project contains an entity model using EF6. My dll will be called as a plugin to an external application, that belongs to a software suite for some hardware products.
I have visual studio set up so that when I press debug it launches this external application (i will refer to as the gateway) which in turn makes calls to my dll, allowing me to debug.
The issue occurs when my dll tries to make calls to the entity model. I get:
InvalidOperationException -- An unhandled exception of type 'System.InvalidOperationException' occured in ENTITYFRAMEWORK.dll
'No connection string named 'Entity' could be found in the application config file.
Now, my config file has, very clearly, the required connection string which was added by VS when I set up the model. I have read all of the similar threads to this issue, and adding the connection string to the config is not the problem.
The gateway does have knowledge of the real DB instance and is given the connection string for that in a configuration. However, the entity connection string and the instance connection string differ, because of the entity jargon that gets added on by VS and EF.
I am able to create a console app which makes calls to my dll, capable of making the enity calls. I had to give the console app a reference to my dll and entity framework as well as add the connection string to the console apps config file.
This has led me to believe that, any app that makes calls into my dll must have knowledge of EF and the connection string.
Is this the case? If so, it would appear to me that I will be unable to use EF for this project because I will have no way to make the gateway aware of EF.
Thanks for your input!
So what I would do in this case is make a new Context which inherits from your current context and in the constructor pass in the connection string.
Alternatively you can also create a connection string that you can then pass into the constructors overload for your context.
public string GetConnectionString()
{
string connectionString = new EntityConnectionStringBuilder
{
Metadata = "res://*/Data.System.csdl|res://*/Data.System.ssdl|res://*/Data.System.msl",
Provider = "System.Data.SqlClient",
ProviderConnectionString = new SqlConnectionStringBuilder
{
InitialCatalog = ConfigurationManager.AppSettings["SystemDBName"],
DataSource = ConfigurationManager.AppSettings["SystemDBServerName"],
IntegratedSecurity = false,
UserID = ConfigurationManager.AppSettings["SystemDBUsername"],
Password = ConfigurationManager.AppSettings["SystemDBPassword"],
MultipleActiveResultSets = true,
}.ConnectionString
}.ConnectionString;
return connectionString;
}
Can't you compose the Entity connectionstring based on the sql connection string?
Otherwhise have a look at this question: How to have DLL specific config file?
Basicly you are supplying a config for the dll file. So besides of myapplication.exe.config you can have a myddl.dll.config

Azure web site deployment throwing. Mislead between DataBaseFirst and CodeFirst

I'm stuck with this "dreadful" error message trying to deploy an MVC web site on Azure :
Code generated using the T4 templates for Database First and Model
First development may not work correctly if used in Code First mode.
To continue using Database First or Model First ensure that the Entity
Framework connection string is specified in the config file of
executing application. To use these classes, that were generated from
Database First or Model First, with Code First add any additional
configuration using attributes or the DbModelBuilder API and then
remove the code that throws this exception.
DataBase First Workflow was used from scratch (adding ADO.Net Entity Data Model element and following wizzard connecting to an Azure SQL Server DB). So I can't figure out why it's besetting me with Code First. Using EF 6.0 with T4 templates. Generated DbContext looks like this :
public partial class MyAppEntities : DbContext
{
public MyAppEntities()
: base("name=MyAppEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<AType> AType { get; set; }
public virtual DbSet<BType> BType { get; set; }
// etc.
}
Connection string looks like this. Copied both in DAL project and StartUp project web config :
<add name="MyAppEntities" connectionString="metadata=res://*/MyAppModel.csdl|res://*/MyAppModel.ssdl|res://*/MyAppModel.msl;provider=System.Data.SqlClient;provider connection string="data source=ndkkyxvogj.database.windows.net;initial catalog=DbName;persist security info=True;user id=myuserid;password=Pa$$word;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
App runs without any problem on local machine.
Deploying process on Azure follow these steps.
Create (custom creation) web site on Azure and give db credentials
Download publish profile from Azure dash board
In VS click Publish from start up project and set following parameters :
-> Profile : Import downloaded profile
-> Connection : Connection well set and validates
-> Settings : Not sure at all what is awaited here !!! I tryed both connection settings : With suggested connection strings and with EDMX connection string. like this :
metadata=res:///MyAppModel.csdl|res:///MyAppModel.ssdl|res://*/MyAppModel.msl;provider=System.Data.SqlClient;provider connection string="data source=ndkkyxvogj.database.windows.net;initial catalog=MyDb;persist security info=True;user id=databaseuser;password=Pa$$word;MultipleActiveResultSets=True;App=EntityFramework"
Tryed to comment OnModelCreating(). Didn't work.
Also tryed to comment throw on UnintentionalCodeFirstException(). Didn't work either.
Despite research on other SO Q & A, couldn't find any reliable solution. Any help would be greatly appreciated.
Ok got it ...
Actually, falling on that post and that one, it appears that it is Azure misleading between the connection string names both given the same in Azure Sql Server and the Azure Web Site.
It has nothing to do with a whatsoever bad EF implementation between code first/model first or db first ...
So I gave connection string name a new one in the web App config, Context Class constructor, and in the azure web sites connection string name parameters ... And it worked.
It was a real pain figuring this out ...

Sharing DB Access Methods between Client and Server in Entity Framework (C#.Net)

it's a kind of client-server architecture problem.
I have 2 projects in my solution: one project for the client side working with Entity Framework and SQL Server Compact database and another one for the server side also working with Entity Framework but with a real SQL Server database. Both databases have exactly the same database schema, so although they are using different .edmx files, the generated entities looks the same and only differ in namespaces. By the way I'm using the ADO.NET DbContext Generator to generate persistence ignorant entity classes. So far so good. Now I wrote a (quite large) class with all the server database access methods inside, e.g.:
public User CreateUser(string userId, string username, bool isGlobalAdmin)
{
using (var context = new ServerEntities())
{
try
{
var user = new User
{
UserID = userId,
Username = username,
IsGlobalAdmin = isGlobalAdmin
};
context.User.Add(user);
context.SaveChanges();
return user;
}
catch (Exception ex)
{
HandleEfException(ex);
}
}
return null;
}
The problem is that I need the same class with the same methods on the client side. So I would copy this class to the client project, rename ServerEntities into ClientEntities and change the namespace for using client entities. This is quite ugly, because I need to maintain both classes, if something changes. Is there a way to abstract the whole thing and use the same class (which is located in a separate prject the other two projects refer to) on both sides (client and server)?
I would really appreciate your help.
Best,
Antony
If the databases are guaranteed to be identical, why do you need both sets of entities? Just use one set so they are interoperable.
You can do the following:
#if SERVER
using (var context = new ServerEntities())
#elif CLIENT
using (var context = new ClientEntities())
#endif
Then, in the project properties for both projects, under Build and then the Conditional Compliation Symbols box, you can add the token for each. So, in the server project, add SERVERand in the client, add CLIENT. If there are already tokens there, separate with semicolon (;).
Whichever project you put the class in, add it as a link to the second project. For instance, if the class file lives in the server project, in the client project, go to Add -> Existing item. Select the file, but then click the arrow by Open and click "Add as Link". This will ensure there is only one copy linked to both projects.
When each is compiled, the compiler will look at the tokens, evaluate them, and it will use the ClientEntities line in the Client project and the ServerEntities in the Server project.
You can do the same preprocessor directives for namespaces if needed. Here is an MSDN article explaining the directives.

Categories

Resources