This is an odd one. All the sudden when I create LINQ to SQL projects in Visual Studio would it not create the following line in the designer, up to three weeks ago or so, it used to create this line, now I have to manually do it. Then if I make changes in the dbml file it removes it and I have to manuallhy add again. huge pain. Here is the lines I am speaking of:
public DataContext():
base(global::System.Configuration.ConfigurationManager.ConnectionString["SiteSqlServer"].ConnectionString, mappingSource)
{
OnCreated();
}
I am using Visual Studio 2008 sp1.
It's a known problem.
You have to implement sort of factory for DB context. Otherwise you will always stuggle with the designer and never know which connection you are using.
public partial class CustomDataContext {
public static CustomDataContext Create()
{
return new CustomDataContext(ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString);
}
}
Another option is inheriting from your CustomDataContext, and creating a default constructor:
public CustomDataContext : InternalCustomDataContext /* created in designer */
{
protected string GetCustomConnectionString() {
return ConfigurationManager.ConnectionStrings["CustomConnectionString"].ConnectionString;
}
public CustomDataContext() : base(GetCustomConnectionString())
{}
}
Look at the connection properties in the linq2sql designer, try the different settings until you find the one that creates that initializes the connection in the context.
I recall receiving that in a project, and as far as I remember its related to the way you make/configure the connection. I fixed it at the time, but I don't recall the exact property/place.
Related
I am getting frustrated about this, as I have tried out everything.
I have a backend project which uses EF6 (6.4.4) to connect to the database. There I have a DbContext:
public partial class WorkobjectContext : DbContext
{
public WorkobjectContext()
: base(DatabaseManager.ConnectionString)
{
// Set the initializer to null to disable intializtion otherwise EF tries to create the table if it does not exist (CreateDatabaseIfNotExists)
Database.SetInitializer<WorkobjectContext>(null);
}
public virtual DbSet<DomainLayer.WorkobjectView> WorkobjectViews { get; set; }
}
Where DatabaseManager.ConnectionString is defined as following:
public static String ConnectionString => System.Configuration.ConfigurationManager.ConnectionStrings["MainConnectionString"].ConnectionString;
Now I have a UI project which uses this backend and it works perfect. I can use the backend and load data with EF6 from my oracle database.
The problem happens when I create a user control and reference WorkobjectContext:
var context = new WorkobjectContext();
Still here the UI-Application compiles successfully. But as I try to add this user control to somewhere else (another user control or a form) then the designer of Visual Studio 2015 does not work and shows the following error:
The argument 'nameOrConnectionString' cannot be null, empty or contain only white space.
The callstack shows the following error message:
at System.Data.Entity.Utilities.Check.NotEmpty(String value, String parameterName)
at System.Data.Entity.DbContext..ctor(String nameOrConnectionString)
at Workflow.Backend.InfrastructureLayer.Context.WorkobjectContext..ctor() in Workflow.Backend\InfrastructureLayer\Context\WorkobjectContext.cs:line 14
at Inbox.Modules.UcWorkobjectFilterPane..ctor() in Inbox\Modules\Workobjects\UcWorkobjectFilterPane.cs:line 26
This is despite the fact that the project is compiled and run successfully.
I tried different things to overcome this problem:
Assign the connectionstring directly to DatabaseManager.ConnectionString: public static String ConnectionString => "DATA SOURCE=XXX-XXX-XXX.XXX:3333/XXX.TSTFRA;PASSWORD=XXX;USER ID=XXX";
Change the constructor of WorkobjectContext: public WorkobjectContext() : base(DatabaseManager.ConnectionString!= null ? DatabaseManager.ConnectionString: "DATA SOURCE=XXX-XXX-XXX.XXX:3333/XXX.TSTFRA;PASSWORD=XXX;USER ID=XXX")
None of them works and the designer fails and shows the mentioned error message.
What is the reason for this problem? How can I overcome that?
UPDATE:
I found out, if I do the following:
public WorkobjectContext() : base("DATA SOURCE=XXX-XXX-XXX.XXX:3333/XXX.TSTFRA;PASSWORD=XXX;USER ID=XXX")
and clean and rebuild the solution and restart visual studio (important to restart visual studio), then the error disappears. After restarting, I can undo the change:
public WorkobjectContext() : base(DatabaseManager.ConnectionString)
and the error is not shown until I restart visual studio again. After restarting the visual studio with the undone changes, then the error reappears.
What is the reason for this problem?
UPDATE:
My last achievement:
If I change DatabaseManager.ConnectionString to the following, then the designer seems to work and does not show any error messages:
public static String ConnectionString => System.Configuration.ConfigurationManager.ConnectionStrings["MainConnectionString"] != null && !String.IsNullOrEmpty(System.Configuration.ConfigurationManager.ConnectionStrings["MainConnectionString"].ConnectionString) ? System.Configuration.ConfigurationManager.ConnectionStrings["MainConnectionString"]?.ConnectionString :
"DATA SOURCE=XXX-XXX-XXX.XXX:3333/XXX.TSTFRA;PASSWORD=XXX;USER ID=XXX";
GOAL using Database-First Paradigm (not Code-First) for a deployed desktop wpf application, with unique databases for end users:
1) Have EntityFramework use a connection string determined at run time.
2) Not deploy different app.config files.
Things attempted:
1) Overload the constructor - while successful, this solution is undesired as it leaves the door open for developers to make mistakes, makes unit testing more difficult.
2) Attempted modifying the connection / context factory - threw Exception.
3) Change the default constructor - could be successful, this solution is undesired as the default constructor is autogenerated.
4) Attempted modifying the ConfigurationSettings - threw Exception, it is read-only.
5) Have a customer side deployment of app.config - while plausible, this solution is undesired as it requires a rewrite of our deployment engine.
Help?
EDIT:
Some code related to first item we tried (overloading the constructor):
public partial class DatabaseContext
{
public DatabaseContext(EntityConnection con)
: base(con, true)
{
}
}
public static class DbContextHelper
{
public static string ConnectionString { get; set; }
public static CounterpartDatabaseContext GetDbContext()
{
EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder
{
Provider = "System.Data.SqlClient",
ProviderConnectionString = ConnectionString,
Metadata = #"res://*/DatabaseContext.csdl|res://*/DatabaseContext.ssdl|res://*/DatabaseContext.msl"
};
EntityConnection con = new EntityConnection(builder.ToString());
return new DatabaseContext(con);
}
}
Usage:
public void SomeMethod()
{
using(DatabaseContext db = DbContextHelper.GetDbContext())
{
// db things
}
}
EDIT code for adding connection string with config manager:
public MainWindow()
{
InitializeComponent();
ConfigurationManager.ConnectionStrings.Add(new ConnectionStringSettings("DatabaseContext", #"metadata=res://*/DatabaseContext.csdl|res://*/DatabaseContext.ssdl|res://*/DatabaseContext.msl;provider=System.Data.SqlClient;provider connection string="data source=sqldev;initial catalog=Dev;persist security info=True;user id=user;password=password;MultipleActiveResultSets=True;App=EntityFramework"", "System.Data.EntityClient"));
}
the config manager code just throws an exception, so no point in any code after that.
Generated DatabaseContext class is both partial. With partial you can add code in another file (just remember about partial keyword there) and still be to re-generate everything. Generator will only overwrite the file it generated, all other files with extra additions to that partial class will not evaporate. No problem with mantaining generated and handwritten parts there.
Also, the generated class is not sealed. You can inherit from it. So, instead of using DatabaseContext directly, you might try inheriting from it and start using the derived class. This derived class will not inherit the constructors, but will inherit all other public important things. You will be able then to provide your own constructor, even default one, that will i.e. call parameterized base class ctor. Actually, I have not tried it that way, but it looks simple and may work.
What I propose is not using DbContextHelper.GetContext() (which is static obviously) (which you think the devs may misuse or forget), but rolling in your own DbContext class.
In the project where you have the EDMX and generated DatabaseContext context, add a file with:
public partial class DatabaseContext
{
protected DatabaseContext(string nameOrConnstring) : base(nameOrConnstring) { }
}
it will add a new overload, it will expose the base DbContext constructor that takes the connstring.
Then add another file to that:
public class ANewContext : DatabaseContext
{
public ANewContext() : base(DbContextHelper.FindMyConnectionString()){ }
}
and that's all. Since your helper was static anyways, then we can call it like that. Just change it to return the connstring props, which it had needed to determine anyways.
Now rename the classes:
DatabaseContext -> InternalDatabaseContextDontUseMe
ANewContext -> DatabaseContext
or something like that, and I bet noone will be ever confused as to which one of them should be used everywhere. Usage:
public void SomeMethod()
{
using(var db = new DatabaseContext()) // that's ANewContext after renaming
{
...
}
}
With partial in the InternalDatabaseContextDontUseMe, you will be able to regenerate the model, and the extra added ctor will not be deleted. With one extra inheritance level, the autogenerated default constructor will be hidden, and devs using the derived class will not be able to accidentally call it, they'll receive new default ctor that will do what's needed.
If you are really interested in hearing about what I found while digging in the EF source, LazyContext, Factories, Resolvers and etc, look at this article of fine. I put there everything I could recall today and while it's somewhat chaotic, it may help you if you like digging&decompiling. Especially the EntityConnection-DbProviderFactory-Resolvers mentioned at the end.
VS2012 for desktop .net framework 4.5 normal windows forms applications, not WPF
Hello, I tried to search for an answer, but I'm not sure of the correct terminology. I've managed to break my code, and can't understand what I've done wrong. (i didn't think i had changed anything, but ...)
I have a solution which contains 2 projects. The first project is an executable program, and the second is a DLL, which is loaded at run time and used by the first project.
the first project contains a form, and a static class with public static strings in the same namespace. (and some other unconnected classes). specifically:
namespace project1_namespace
{
static class settings
{
public static string some_words = "some words in a string";
}
class dll_callback{
//.. some public methods here
}
dll_callback dllcallback; // instance is initialised in the code (not shown)
Form form;
public partial class frm_splash : Form
{
private void frm_splash_FormClosing(object sender, FormClosingEventArgs e)
{
// this function actually loads the DLL, ensuring its the last step
//... some error checking code removed for brevity
Assembly assembly = Assembly.LoadFrom("c:\dllpath\project2.dll");
Type type_init = assembly.GetType("project2_class");
object init = Activator.CreateInstance(type_init, form, dllcallback);
//... some error checking code removed for brevity
}// end method
}// end form class
}// end namespace
when the form is closing, the method shown above is called which calls the second projects class project2_class constructor.
in project 2, the DLL, there is:
namespace project2_namespace
{
// how did i get this working to reference "settings" class from project 1??
public class project2_class
{
public project2_class(project2_namespace.Form1 form_ref, object callback)
{
settings.some_words = "the words have changed";
//... some more stuff
}
}
}
Now, i was experimenting with some code in an entirely different part of project2, and VS2012 suddenly started refusing to compile stating:
error CS0103: The name 'settings' does not exist in the current context
the standard solution to this appears to be to add a reference to project2, but that would create circular dependencies because project 1 calls 2 as a DLL.
I really honestly don't think i had changed anything relevant to this, but also clearly I have.
looking at it, i cant see how project 2 would have access to a class in project 1 without a reference, but the list of arguments to the project2_class constructor doesn't include one, and I am absolutely positive that it hasn't changed (and I cant change it for backwards compatibility reasons).
would really appreciate help with this, as its been a lot of work to get this working.
as a side note, I've definitely learned my lesson about not using source control. and not making "how this works" comments instead of "what this does" comments.
may dynamic help you? You can not get the setting string at complie time.
I'm writing an WPF application using Entity Framework and I have two controls, Window and UserControl which is embedded in Window. UserControl designer works fine, but Window designer returns an exception:
The specified named connection is either not found in the configuration, not
intended to be used with the EntityClient provider, or not valid.
The exception points at line in UserControl code-behind where I create an instance of my entities.
public partial class Table : UserControl
{
private MyEntities entity;
public Table()
{
InitializeComponent();
entity = new MyEntities();
}
}
When I run the app everything works fine.
EDIT
I found the solution here: WPF designer won't load with entity framework , although I'm using VS2010 and some time ago this approach (creating an instance of entities in the same place) worked fine, I don't know what broke it down.
The problem, most likely, is with the initialisation call in the design mode which is why code runs just fine.
Your Entity should be based on two files: FileName.edmx and FileName.Designer.vb (or .cs if using C#). When in design mode, the Window tries to create new instance of UserControl which in turn creates new instance (makes call to New) of the Entity. However, in design mode, VS doesn't look at the App.Config file (it looks there is debug mode) where the connection string for Entity is kept. Hence when VS tries to create the new Entity, one of the methods inside the Entity initialisation call fails because it receive Null connection string and as result you get your error.
A quick and dirty fix is to put in the connection string by hand in the FileName.Designer.vb (FileName.Designer.cs). If you open that file (you may have to click "Show All Files" in Solution Explorer), there should be, in Constructors region,
Public Sub New()
MyBase.New("name=Entity"," "Entity")
End Sub
or in C#
public New()
{
MyBase.New("name=Entity"," "Entity");
}
if you replace the first argument of the call with the connection string from App.Config to get MyBase.New(ConnectionStringFromAppConfig," "Entity"), everything should work fine. One problem you might get is error message similar to "Keyword not supported: 'data source'." To fix this, you need to replace in the connection string you copied all the " with single quote. " is XAML way of coding single quote.
Hope that helps. If somebody were to contribute a more elegant solution - i would be grateful.
I'm getting the following exception:
The number of members in the
conceptual type 'MyModel.Customer'
does not match with the number of
members on the object side type
'MyNamespace.Customer'. Make sure the
number of members are the same.
In the following code:
public CusomserService
{
// ...
public IEnumerable<Customer> GetCustomers()
{
return new Repository<Customer>().All();
}
}
public class Repository<T>() where T : EntityObject
{
// ...
public IQueryable<T> All()
{
return _context.CreateObjectSet<T>().AsQueryable<T>(); /* HERE THE EXCEPTION IS THROWN */
}
}
The generics repository was working fine until I made some changes in my EF Model. I'm letting EF create the database (through Generate database from Model option).
Where do I start?
EDIT: I've solved it.
The problem had nothing to do with EF or my model. I had renamed the data layer project (and it's assembly name) from original_name.dll to new_name.dll. I had updated the service layer project reference to the data layer project, but the the old assembly (original_name.dll) was still in the bin directory. Deleting the old assembly from the service layer's bin directory and rebuilding the solution solved the problem.
It seems that Classes 'MyModel.Customer' does not match with each other 'MyNamespace.Customer'.
Try right clicking on the edmx file and selecting Run Custom Tool
or right click on edmx in solution explorer and open with xml and verify your recent changes.