Extending System.Data.Linq.DataContext - c#

I have a class reflecting my dbml file which extends DataContext, but for some strange reason it's telling me
System.Data.Linq.DataContext' does not contain a constructor that takes '0' arguments"
I've followed various tutorials on this and haven't encountered this problem, and VS doesn't seem to able to fix it.
Here's my implementation
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
using System.Text;
using IntranetMvcAreas.Areas.Accounts.Models;
namespace IntranetMvcAreas
{
partial class ContractsControlDataContext : DataContext
{
[FunctionAttribute(Name="dbo.procCC_Contract_Select")]
[ResultType(typeof(Contract))]
[ResultType(typeof(ContractCostCentre))]
[ResultType(typeof(tblCC_Contract_Data_Terminal))]
[ResultType(typeof(tblCC_CDT_Data_Service))]
[ResultType(typeof(tblCC_Data_Service))]
public IMultipleResults procCC_Contract_Select(
[Parameter(Name = "ContractID", DbType = "Int")] System.Nullable<int> ContractID,
[Parameter(Name = "ResponsibilityKey", DbType = "Int")] System.Nullable<int> ResponsibilityKey,
[Parameter(Name = "ExpenseType", DbType = "Char")] System.Nullable<char> ExpenseType,
[Parameter(Name = "SupplierID", DbType = "Int")] System.Nullable<int> SupplierID)
{
IExecuteResult result = this.ExecuteMethodCall(this, (MethodInfo)(MethodInfo.GetCurrentMethod()), ContractID, ResponsibilityKey, ExpenseType, SupplierID);
return (IMultipleResults)result.ReturnValue;
}
}
}
And it's ContractsControlDataContext that's pointed at as the problem
(btw, this has no relation to a very recent post I made, it's just I'm working on the same thing)
EDIT
It's probably worth clarifying this, so please read very carefully.
If you do not extend DataContext in the partial class, then ExecuteMethodCall isn't accessible.
'Intranet.ContractsControlDataContext' does not contain a definition for 'ExecuteMethodCall' and no extension method 'ExecuteMethodCall' accepting a first argument of type 'Intranet.ContractsControlDataContext' could be found (are you missing a using directive or an assembly reference?)
Maybe I'm missing something incredibly stupid?
SOLVED
I think perhaps Visual Studio struggled here, but I've relied entirely on auto-generated code. When right clicking on the database modeling language design view and hitting "View Code" it automagically creates a partial class for you within a specific namespace, however, this namespace was wrong. If someone could clarify this for me I would be most appreciative.
The .designer.cs file sits in namespace Intranet.Areas.Accounts.Models, however the .cs file (partial class generated for the .designer.cs file by Visual Studio) was in namespace Intranet. Easy to spot for someone more experienced in this area than me.
The real problem now is, who's answer do I mark as correct? Because many of you contributed to finding this issue.

The object DataContext for linq does not have an empty constructor. Since it does not have an empty constructor you must pass one of the items it is excepting to the base.
From the MetaData for the DataContext.
// Summary:
// Initializes a new instance of the System.Data.Linq.DataContext class by referencing
// the connection used by the .NET Framework.
//
// Parameters:
// connection:
// The connection used by the .NET Framework.
public DataContext(IDbConnection connection);
//
// Summary:
// Initializes a new instance of the System.Data.Linq.DataContext class by referencing
// a file source.
//
// Parameters:
// fileOrServerOrConnection:
// This argument can be any one of the following: The name of a file where a
// SQL Server Express database resides. The name of a server where a database
// is present. In this case the provider uses the default database for a user.
// A complete connection string. LINQ to SQL just passes the string to the
// provider without modification.
public DataContext(string fileOrServerOrConnection);
//
// Summary:
// Initializes a new instance of the System.Data.Linq.DataContext class by referencing
// a connection and a mapping source.
//
// Parameters:
// connection:
// The connection used by the .NET Framework.
//
// mapping:
// The System.Data.Linq.Mapping.MappingSource.
public DataContext(IDbConnection connection, MappingSource mapping);
//
// Summary:
// Initializes a new instance of the System.Data.Linq.DataContext class by referencing
// a file source and a mapping source.
//
// Parameters:
// fileOrServerOrConnection:
// This argument can be any one of the following: The name of a file where a
// SQL Server Express database resides. The name of a server where a database
// is present. In this case the provider uses the default database for a user.
// A complete connection string. LINQ to SQL just passes the string to the
// provider without modification.
//
// mapping:
// The System.Data.Linq.Mapping.MappingSource.
public DataContext(string fileOrServerOrConnection, MappingSource mapping);
Something as simple as this would work. Any class that inherits from the DataConext must pass to the base constructor at least one of the types it is excepting.
public class SomeClass : System.Data.Linq.DataContext
{
public SomeClass(string connectionString)
:base(connectionString)
{
}
}

I'm assuming that the namespace and (data-context) type name are correct... double check that first.
It sounds to me like the codegen has failed, and so you only have your half of the data-context (not the half that the IDE is meant to provide). There is a known bug in LINQ-to-SQL where this can fail if (as in your case) the using declarations are above the namespace. No, I am not joking. Try changing the code:
namespace IntranetMvcAreas
{
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
using System.Text;
using IntranetMvcAreas.Areas.Accounts.Models;
// the rest of your code
Now go into the designer, tweak something (for example, change the name of a property and change it back again) and hit save (this forces the codegen). Now see if it works.

David Basarab's answer is correct and should be marked as the answer.
Your class is not providing any constructor, so a default constructor is provided. Default constructors for derived classes can only be provided if the base class has a parameterless constructor. However, the DataContext class which is your base class in this example does not provide a parameterless constructor. This explains the error message the compiler returned to you.
Edit:
Example:
class A {
public A(string s) {
}
}
class B : A {
}
An attempt to compile that returns an error in class B:
'A' does not contain a constructor that takes '0' arguments

The behavior of the generator regarding constructors is controlled, to some extent, by the Connection properties of the DBML. If Application Settings is True, and there is a settings property name, it will generate a constructor that reads the connection string from the Application Settings of the assembly.
If there is a connection string, it will generate a constructor with a hardcoded connection string in the .designer.cs file.
If there is neither, it will not generate a constructor without a connection string parameter, and you can safely provide a parameter-less constructor in a partial class without causing a conflict.
These settings changes don't survive a round trip of the schema from the database, but I simply clear the connection settings from the properties after making changes and before I save the DBML.

#Sander: I think you were on the right track. Instead of using a partial class and implementing the function for the sproc I instead followed this blog and used the *.designer.cs file for implementing it. Whilst I'm still experiencing problems with invalid type casting it did get rid of the original problem.

Related

Switchable connection strings via code at run time

I have a WPF application. It has many blocks that access the database. The connection string is determined by a setting in my App.config file.
using (var dbContext = new MyEntities())
{
// ...
}
But now I need the ability to switch between different databases at run time. I've updated the code to manage a list of databases, along with a connection string to each one.
My question is, is there any way to have the existing code using the connection string indicated by my code without having to change the existing code? For example, perhaps I can create a static connection string property in my entities class, and then modify that class to use the property each time it connects to the database.
Has anyone done this? Any tips to do this in a painless way?
So the best idea I came up with was to add a static ConnectionString property to my entities class. And then modify the constructor to pass this property to the base class.
One issue is that any change to the entities class would be overwritten by the T4 scripts when the model is updated. You could create a partial class and define your own constructor, but if that constructor has no arguments then it will conflict with the existing constructor.
My solution for this was to actually edit the existing T4 script directly, as shown below.
<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
{
// Original code
//public <#=code.Escape(container)#>()
// : base("name=<#=container.Name#>")
//{
// Modified code
public static string ConnectionString { get; set; }
public <#=code.Escape(container)#>()
: base(ConnectionString)
{
// End of modified code
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
When you save the T4 script, it will immediately regenerate the code.

Unable to reference a design-time ViewModel in Xaml

I've done this before, but not for some time and clearly I'm missing something.
In short, I've got a design-time model that inherits from my real view model and sets some properties in the constructor.
I'm importing the namespace in Xaml and IntelliSense is suggesting the desired class name, which leads me to believe my naming is error-free.
Even after a clean/build, I'm getting an error saying that the referenced model doesn't exist.
I can refer to the model from a .cs using Aurora.UI.ViewModels.SecurityViewModel_DesignTime without issue.
(In case it matters, this project has a target of x64. This is due to a dependency on an bit-dependent library. It's the only real difference I can point to when comparing to previous implementations).
The name "SecurityViewModel_DesignTime" does not exist in the namespace "clr-namespace:Aurora.UI.ViewModels"
And the model itself:
namespace Aurora.UI.ViewModels {
public class SecurityViewModel_DesignTime : SecurityViewModel {
public SecurityViewModel_DesignTime() {
this.Sensor = new Peripherals.Kinect();
this.PrimaryFeed = Kinect.Feed.Infrared;
Feeds = new List<Kinect.Feed> {Kinect.Feed.Infrared};
this.LookDirections =
Peripherals.Kinect.DirectionsRequired.Front |
Peripherals.Kinect.DirectionsRequired.Left |
Peripherals.Kinect.DirectionsRequired.Right |
Peripherals.Kinect.DirectionsRequired.Top;
}
}
}
(The class it's inheriting from is the 'real' viewModel and is a simple POCO)
What am I missing?
As per the comment, here's an answer:
Do a solution clean, and restart visual studio. Goodness knows why it works. The designer is janky at the best of times.

unsupported class hierarchy change in Db4o

I have:
static class Db4o...
and:
class Db4oBase... // which uses Db4o class
where I can:
class Customer : Db4oBase
{
public Customer(string name)
{
}
}
so that I can:
Customer customer = new Customer("Acbel Polytech Philippines");
customer.store(); //something like that
It worked, until sometime in my development, the code below suddenly bugged down:
class Db4o
{
.
.
.
public static IObjectSet Retrieve(object obj)
{
IObjectSet objectSet = null;
objectSet = container.Ext().QueryByExample(obj); // This part of the code
// throws a unsupported
// class hierarchy.
return objectSet;
}
}
The QueryByExample instruction throws an unsupported class hierarchy. Does anybody know what should I do?
It happened when you:
Code a class and then run the program.
Later you modify the code and add/change the parent class (changing the hierarchy)
Finally you run again and ... CRASSHHH.
yes, Hierarchy (inheritance) is supported but change it is not so simple to apply on existent file.
Somehow your class hierachy has changed -- which is not directly supported by db4o. What ever happend, you have the following options (from db4o docs):
Create the new hierarchy with different names, preferably in a new
package
Copy all values from the old classes to the new classes.
Redirect all references from existing objects to the new classes.
Okay this is what I did to remove the exception. I just created another clean database file. But I haven't find out what is the root cause that led to that error. No time for that yet. But it removed the "Unsupported class hierarchy change" exception. So if any of you encountered this you might want to try doing what I've done but if you know the root cause, please post it here as an answer. Thanks.

Custom Expression in Linq-to-Sql Designer

According to Microsoft:
http://msdn.microsoft.com/de-de/library/system.data.linq.mapping.columnattribute.expression.aspx
It's possible to add expression to the Linq-to-SQL Mapping.
But how to configure or add them in Visual Studio in the Designer?
Problem, when I add it manual to thex XYZ.designer.cs it on change it will be lost.
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4927
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
This is generated:
[Column(Name="id", Storage="_id", DbType="Int")]
public System.Nullable<int> id
{
...
But i need something like this
[Column(Name="id", Storage="_id", DbType="Int", Expression="Max(id)")]
public System.Nullable<int> id
{
...
Thanks.
According to this article:
http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.columnattribute.expression.aspx
you should use the ColumnAttribute.Expression Property when you use CreateDatabase to define a column as containing computed values.
So you should check this article:
http://msdn.microsoft.com/en-us/library/Bb399420%28v=VS.100%29.aspx
Another way is to define expression on your sql server so it'll be mapped by the LINQ designer.
Edit: mmmm you edited your question, so probably my answer is not gonna help you so much, but you might be able to do this anyway with your 'extended' question :D
I do this by adding another class file to the project, give them the same name as the object from LinQ-to-SQL you want to extend and define it as partial.
for example, if you have a table called Files, the object File will be created for you by L2S. If you then create a file (with the same namespace as your DataContext object), and make it partial, like this:
public partial class File
{
}
You can just add properties, methods, etc. From within this class, you also have direct access to the properties of the 'other' File class.
It's a little klugy, but in your linq2sql designer, rename the field from 'id' to 'xid' (or anything else) and change its accessibility to internal.
then, in another file, start another partial class, like Wim Haanstra showed, and create a new property called 'id', add all the attributes you want, and in the get & set, just map it to and from the original property, now called 'xid'.
it would look something like this:
public partial class File
{
public int? id
{
get { return xid; }
set { xid = value; }
}
}
this is more commonly done to map fields in the database to a different type in the object, e.g. an int in the DB to an enum in the object, a byte/smallint/etc. in the DB, a boolean in the object. or to add attributes, like [DataMember] to the property.

Linq to SQL DataContext Lifetime Management Issue

I read Rick Strahl's article about ways to deal with the data context. My DBML is inside a class library, I keep my data context open by creating a static Current method in a separate custom partial class within library.
public partial class DataContext
{
public static DataContext Current
{
get
{
DataContext dc = HttpContext.Current.Items["dc"] as DataContext;
if (dc == null)
{
dc = new ImmediacyPageDataContext();
HttpContext.Current.Items["dc"] = dc;
}
return dc;
}
}
then access it like this
DataContext dc = DataContext.Current;
However, this causes issues whenever I update my DBML file. After editing the DBML file whenever I try and build the project my designer file doesn't regenerate/gets deleted. If I try running the custom tool option it comes back with an error.
The only way I can get round this is by renaming or deleting the custom partial class, re-generating the designer file, then adding my custom partial class back into the solution. This is a does work, but.. its a bit of a pain.
Is there a better approach to take that will make editing my DBML files easier, while prolonging my DC for as long as possible ?
Go into the code file with your partial DataContext class and move your using statements into your namespace. For some reason the tool will not generate the designer unless this is the case.
namespace MyNamespace
{
using System;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
using System.Xml.Linq;
partial class DataContext
{
}
}
I believe this change was required when moving from VS2008 to VS2008 SP1, though I may be mixing up some versions.
You should create your partial class in a different file, not the .designer.cs file. The easiest way to do this is to right-click on your DBML in the solution explorer (or in a blank area in the DBML designer) and click "View Code". This will create a new .cs file that won't be overwritten when you save your DBML.
I don't believe your DataContext persistence and DBML issue are related. It sounds like the IDE is confused versus a conflict with a Cached DataContext (HttpContext.Current.Items is per Request so there's no long-term caching anyway).
I had trouble with DBML compilation when my data model contained a class name that conflicted with another class. For instance, a DBML object named 'Application' (an insurance application) might conflict with HttpApplicationState.Page.Application.
Check your error message and see if it's specific to a name in your DBML.
I can't think of an overly compelling reason why your new static property must be part of the DataContext class. It would be just as easy to have it in a different class.

Categories