I have been sharing database variables using the following code:
Namespace DataAccessVariables
Public Class Vars
Public Shared s As String
Public Shared con As String = WebConfigurationManager.ConnectionStrings("Dev").ToString()
Public Shared c As New SqlConnection(con)
Public Shared x As New SqlCommand(s, c)
End Class
End Namespace
I then import this to my project like this:
Imports DataAccessVariables.Vars
When I check the site with FXCop, I get this message:
Error, Certainty 90, for StaticHolderTypesShouldNotHaveConstructors
{
Target : DBVars (IntrospectionTargetType)
Resolution : "Remove the public constructors from 'Vars'."
Help : http://msdn2.microsoft.com/library/ms182169(VS.90).aspx (String)
Category : Microsoft.Design (String)
CheckId : CA1053 (String)
RuleFile : Design Rules (String)
Info : "Instances of types that define only static members
do not need to be created. Many compilers will automatically
add a public default constructor if no constructor
is specified. To prevent this, adding an empty private
constructor may be required."
Created : 2010/04/20 01:25:16 PM (DateTime)
LastSeen : 2010/04/21 07:17:46 AM (DateTime)
Status : Active (MessageStatus)
Fix Category : Breaking (FixCategories)
}
If I remove the 'Public Shared' from the declarations, then the variables are not picked up in my pages. Can anyone show me the correct way of sharing them?
Thanks a lot,
Phil.
This error isn't telling you to remove the Public Shared variables. Instead it's letting you know that it is possible to create a new instance of your Vars class, even though it includes only Shared members. To resolve the issue, define a private constructor:
Private Sub New()
End Sub
This will prevent any code creating an instance of the Vars class outside of the class itself.
Is that the only code in your class?
Also, you should not create a global (static) SqlConnection. Simply create the SqlConnection and SqlCommand objects on-demand. Connection pooling will ensure that only one physical database connection is made at a time.
The way you've got it here, it's not thread-safe (if two people make a request at the same time, for example, things are going to get really screwy).
Related
So, i want to do what I feel should be such a simple task... pass in a parameter to a constructor using Autofac!
However, I have managed to get a work around working, but just dont think this is correct, I feel i am chaning too much of the recommended code from the Autofac guides
I am more than happy for answers in C# or VB.net it doesnt matter, the location of code is all the same
So, here is my setup (im not fussed about neatness, just trying to get this to work for now)
In my global.asax I have:
'***Note, the autofac guide had this a a private shared, see below for why i changed it***
' Provider that holds the application container.
Public Shared _containerProvider As IContainerProvider
' Instance property that will be used by Autofac HttpModules
' to resolve And inject dependencies.
Public ReadOnly Property ContainerProvider As IContainerProvider Implements IContainerProviderAccessor.ContainerProvider
Get
Return _containerProvider
End Get
End Property
then within my global.asax within application_start I have:
***again, note, originally I was using IMyClass when registering type... not sure this or that is correct***
Dim builder As New ContainerBuilder()
builder.RegisterType(Of MyClass)().As(Of MyClass)().InstancePerLifetimeScope()
'... continue registering dependencies...
' Once you're done registering things, set the container
' provider up with your registrations.
_containerProvider = New ContainerProvider(builder.Build())
As you can see, origianly the _containerProvider was just public, but I have had to make it "Shared" for this to work, this feels wrong right away!
so, now, in my webForm1.aspx.vb I have this:
Public Property MyClass2 As IMyClass
Private _myClass As IMyClass
Now, because I have adjusted the global to "registerType" to use the actual object, not the interface (which, again seems wrong having to change that too), means now my webform public property is not being set (but, because of my work around, i dont need that anyway)
Also, note the private _myClass... this is for my workaround
so, now in my Webform init method, i have the following:
WebForm1.aspx.vb*
_myClass = [Global]._containerProvider.RequestLifetime.Resolve(Of MyClass)(New TypedParameter(GetType(HttpRequest), Request))
which now instantiates my _myClass with the parameter correctly injected in... this is great, whoopadeedoo
...but... I dont think this is correct.
Now, when I didnt need to pass in a parameter to the construtor, it all worked nice, didnt need to change any of the code from the autofac guide, it just worked, set the public property on my webform.aspx page fine, was really nice.
But, as soon as I start to work with a paramter being passed into the construtor, it seems everything needs to be tweaked so it will work? is this correct?
I have even tried the deligate guide from autofac, but that also doesnt work for me at all by doing this within my webForm.aspx page:
Dim container As ILifetimeScope = [Global]._containerProvider.RequestLifetime
Dim myClassFactory As MyClass = container.Resolve(Of MyClass.Factory)
Dim myClassholding As MyClass = myClassFactory.Invoke("ABC")
even tried without the "Invoke", but "cannot be indexed because it has no default property"
Just incase it helps, here is "myClass"
Private _myID as integer
Public Delegate Sub Factory(myID As integer)
Sub New()
End Sub
Sub New(myID As integer)
_myID = myID
End Sub
Public Sub DoSomething() Implements IDfCookieManager.DoSomething
'do something with myID
End Sub
I know I can pass the id in as a parameter to DoSomething, but i want to understand how to pass this into the constructor
so, my questions:
If this is not how to do this (which I am hoping its not correct), how would I do this without needing to change all the global setup??
Is it best to use a deligate factory or just resolve?
do I really need to change the global container to be shared/static, so that i can access the container from within my code?
So, there are two ways, but firstly, shouldnt need to mess around with how Autofac suggests setting up the ContainerProvider in global.asax... i can keep it as non shared (not static), and to access this value I do the following:
Dim cpa As IContainerProviderAccessor = (CType(HttpContext.Current.ApplicationInstance, IContainerProviderAccessor))
Dim scope As ILifetimeScope = cpa.ContainerProvider.RequestLifetime
Also, in our webform.aspx page, Public Property MyClass As IMyClass should not be added when we need to pass in parameters to the constructor when resolving (otherwise it will be resolved before we try to manually resolve it!
1: Passing in using TypedParameter
Here is my adjusted code to pass in the parameters using resolve (including the lines above):
Dim cpa As IContainerProviderAccessor = (CType(HttpContext.Current.ApplicationInstance, IContainerProviderAccessor))
Dim scope As ILifetimeScope = cpa.ContainerProvider.RequestLifetime
Dim myClass As MyClass = scope.Resolve(Of IMyClass)(New TypedParameter(GetType(Integer), 123))
Also, having the public property at the top of my WebForm1.aspx needed to be removed, because that will auto resolve, meaning, if i try to "resolve" the object manually, it has already been automatically resolved by autofac (which is why i thought my code wasnt working initially), and has already instantiated the object with the empty constructor!
2: Using a Deligate Factory
the line Public Delegate Sub Factory(myID As integer) isnt correct, it should use a function for Autofac to automaticly set this up! so should be: Public Delegate Function Factory(myID As integer) as MyClass
In Global.asax, I just need to add this builder.RegisterType(Of MyClass)().InstancePerLifetimeScope(), because we require a parameter and using a factory, we cant append the .As(Of IMyClass)
Finally, our webform1.aspx.vb just needs this:
Dim cpa As IContainerProviderAccessor = (CType(HttpContext.Current.ApplicationInstance, IContainerProviderAccessor))
Dim scope As ILifetimeScope = cpa.ContainerProvider.RequestLifetime
Dim myClassFactory As MyClass.Factory = scope.Resolve(Of MyClass.Factory)
_myClass = myClassFactory.Invoke(123)
however, I tweaked that slightly to this:
Dim cpa As IContainerProviderAccessor = (CType(HttpContext.Current.ApplicationInstance, IContainerProviderAccessor))
Dim scope As ILifetimeScope = cpa.ContainerProvider.RequestLifetime
Dim myClass As MyClass = scope.Resolve(Of MyClass.Factory).Invoke(123)
I am new to MVC, and right now I am trying to work out the example demonstrated in professional Asp.Net MVC 4 by Galloway J and others, in this example I have to do the following :
create 3 classes: Album, Genre, Artist
create DBContext class called MusicStoreDB
create a controller call it store manager.
in the scaffolding options I used MVC controller with read/ write actions and views, using Entity framework
I also set an Initializer to recreate the database always on application start
but when running the solution no database created, what could be the problem I have tried lot of suggestions, even reinstalling the sql server 2008 R2 and, VS 2012 but it dose not work.
this is the global.asax file
Imports System.Web.Optimization
Imports System.Data.Entity
Public Class MvcApplication
Inherits System.Web.HttpApplication
Sub Application_Start()
AreaRegistration.RegisterAllAreas()
Database.SetInitializer(Of MusicStoreDB)(New DropCreateDatabaseAlways(Of MusicStoreDB)())
WebApiConfig.Register(GlobalConfiguration.Configuration)
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters)
RouteConfig.RegisterRoutes(RouteTable.Routes)
BundleConfig.RegisterBundles(BundleTable.Bundles)
AuthConfig.RegisterAuth()
End Sub
End Class
and the MusicStoreDB class
Imports System.Data.Entity
Public Class MusicStoreDB
Inherits DbContext
Public Property Albums() As DbSet(Of Album)
Get
End Get
Set(value As DbSet(Of Album))
End Set
End Property
Public Property Genres() As DbSet(Of Genre)
Get
End Get
Set(value As DbSet(Of Genre))
End Set
End Property
Public Property Artists() As DbSet(Of Artist)
Get
End Get
Set(value As DbSet(Of Artist))
End Set
End Property
End Class
Make sure your DbContext specifies the proper connection string:
public class MyNewContext : DbContext
{
public MyNewContext() : base("DefaultConnection")
{
}
public DbSet<Genre> Genres { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Song> Songs { get; set; }
}
It is DefaultConnection by default, but make sure you changed yours to MusicStoreDB if you want to use your new connection string. I have left mine at default thus far and deployed to Azure effortlessly.
You should be able to use Entity Framework in a new project without setting up any new connection strings. It "just works" using SQL Express.
I'm willing to bet you have a database existing if you connect to (localdb)\v11.0 in SSMS or elsewhere.
Post your global.asax and DbContext if you continue to have problems.
So I faced this same problem today and it turns out that I presumed EF automatically checks on application start whether that DB exists or not; to say the least my hope was way to ambitious.
The EF will only create the DB if it doesn't exist once you invoke the DB context. For example when you first run the application, if on the landing page you don't instantiate the DB context nothing happens.
For the Music Store example if you are following the book, navigate to (using your own port number of course) "http://localhost:34295/StoreManager", that controller's action should instantiate the DBContext if you have been following the book.
Hope this helps anyone who got a little lost like me!
I am trying to learn a new framework (i think) and i have got to a stage where im not sure whats going on.
So i created a class and a Metadata class. My assumption was that i would have had access to the properties but of course i havent.
I read this link http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.metadatatypeattribute.aspx and followed the example. All seems correct but how do i get access to the properties in the class? I was going to add them to the Partial class but since the example on MSDN doesnt do this, i think i may have missed the point and where does the metadata come into play?
<MetadataType(GetType(CustomerMetadata))> _
Partial Public Class Customer
End Class
Public Class CustomerMetadata
Public Property Cid As Integer = 0
Public Property Name As String = String.Empty
End Class
Thanks
I have an asp.net nTier application. The data access layer is a strongly typed DataSet consisting of multiple DataTables with DataAdapters. When the user logs in, they choose which database to connect to (from a table in the membership database). I need to pass the selected connection string into the DataSet object which will remain the same for that users until they log in again.
I'm thinking that the answer might be to create a partial class of the DataSet object where I can pass the connection string into the constructor. Im not sure how to go about this though.
Cheers
You could do this with a partial class.
Assuming your typed dataset is called HurrDurr:
public partial class HurrDurr
{
public HurrDurr(string connex)
{
this._connection = new global::System.Data.SqlClient.SqlConnection();
this._connection.ConnectionString = connex;
}
}
_connection is only initialized if it is null the first time the Connection internal property is accessed.
Finally got to the bottom of this. In a new module I created a partial class to the table adapter which is where I needed to change the connection string, one mistake I was making originally was not specifying the correct namespace.
Below is the partial class I created which allowed me to dynamically change the connection string of one of my table adapters for a table called tblOptions:
Namespace ds1TableAdapters
Partial Public Class tblOptionsTableAdapter
Sub ChangeConnString(ByVal newConn As String)
Me._connection.ConnectionString = newConn
End Sub
End Class
End Namespace
Thanks for the help Will, it got me going in the right direction.
am trying to implement fluent nhibernate in MVC project...there were no build errors... but when i run the project i get this exception
System.Xml.Schema.XmlSchemaValidationException: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has incomplete content. List of possible elements expected: 'meta, subselect, cache, synchronize, comment, tuplizer, id, composite-id' in namespace 'urn:nhibernate-mapping-2.2'.
have no idea what am doing wrong here... the following is the code for opening session factory...
Private Function CreateSessionFactory() As ISessionFactory
Dim sessionFactoryObject As ISessionFactory
sessionFactoryObject = Fluently.Configure().Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005.ConnectionString("Data Source=.\sqlexpress;Initial Catalog=Designs;User ID=sa;Password=root")).Mappings(Function(x) x.FluentMappings.Add(GetType(DesignMap))).BuildSessionFactory()
Return sessionFactoryObject
End Function
this is really driving me nuts....thanks in advance...:)
update-the mappings
the design table map
Public Class DesignMap
Inherits ClassMap(Of Design)
Public Sub DesignMap()
Table("DesignList")
Id(Function(x) x.DesignId)
Map(Function(x) x.DesignType)
References(Function(x) x.Designer, "DesignerId")
End Sub
End Class
the designer table map
Public Class DesignerMap
Inherits ClassMap(Of Designer)
Public Sub DesignerMap()
Table("DesignerList")
Id(Function(x) x.DesignerId)
Map(Function(x) x.DesignerName)
Map(Function(x) x.DesignerCompany)
HasMany(Function(x) x.DesignersDesigns)
End Sub
End Class
new edit-- the entity property looks like this
Public Overridable Property Name() As String
Get
Return _name
End Get
Protected Set(ByVal value As String)
_name = value
End Set
End Property
am i going the right way..?
I'm not quite sure as the mappings seem ok. I can see one error tough, you have only mapped one of your classes:
.Mappings(Function(x) x.FluentMappings.Add(GetType(DesignMap)))
That should not cause this type of error tough. If you add both your mappings and call the method .ExportTo(#"C:\your\export\path") you will get the actual xml mappings. This way it's easier to see the error. You can do that like this:
.Mappings(Function(x) x.FluentMappings.Add(GetType(DesignMap)).Add(GetType(DesignerMap
).ExportTo(#"C:\your\export\path"))
You can also use the method AddFromAssemblyOf (or some other. There is a few choices) if you don't want to add the mappings one by one.
Try exporting the mappings and see if you can find any error. Or you can post the xml mappings and someone else might find something.
There are several things that can cause this. When using automappings, you will get this if you incorrectly specify the assemblies and namespaces to look in. Other things (more likely in your case) that could cause it, are entity properties that aren't marked as public virtual, having an entity constructor with arguments, but neglecting to make a default constructor, or inheriting your entities from a base class.
I would probably first check to make sure all of your entity properties are "public virtual".
found the problem...the constructor for the map was wrong...it should be like this...
Public Class DesignMap
Inherits ClassMap(Of Design)
Public Sub New()
Table("DesignList")
Id(Function(x) x.DesignId)
Map(Function(x) x.DesignType)
References(Function(x) x.Designer, "DesignerId")
End Sub
End Class
problems of working in both C# and vb.net at the same time i guess..!!
and "Matthew Talbert" was correct...making all the properties Overrideable is important..
thanks guys...:)