I have this and I want to use something similar to the way Java uses .class files to be able to call events and use them in my main code.
The problem is that I cannot get the .class file to use my Dims
Form1.vb:
Namespace LFS_External_Client
Public Class Form1
Inherits Form
Private OutGauge As OutGaugeInterface
Dim SpeedPref As String
Dim FuelCapacity As String
Dim Fuel As String
Public Sub New()
InitializeComponent()
End Sub
Private Sub Form1_Load() Handles MyBase.Load
Some Code
GetFuel()
End Sub
End Class
End Namespace
Then in the Dataproccer.vb (.class file):
Public Class DataProcesser
Public Sub GetFuel()
Some Code
Fuel = og.Fuel.ToString() * FuelCapacity
End Sub
End Class
Code was shortened but has all of the relevant and necessary parts.
If you want to use the actual variables from the form instead of passing them through the method calls, you would need to declare them public instead of using dim:
...
Private OutGauge As OutGaugeInterface
Public SpeedPref As String
Public FuelCapacity As String
Public Fuel As String
...
Dim FuelCapacity As String
Private Sub Form1_Load() Handles MyBase.Load
Some Code
DataProcesser.GetFuel(FuelCapacity)
End Sub
Public Shared Sub GetFuel(Byval FuelCapacity as string)
Some Code
Fuel = og.Fuel.ToString() * FuelCapacity
End Sub
Looking at the MSDN page for the Dim Statement.
It states:
Code outside a class, structure, or module must qualify a member
variable's name with the name of that class, structure, or module.
Code outside a procedure or block cannot refer to any local variables
within that procedure or block.
Also according to this MSDN article the default access level for the Dim Statement is Private at the Module Level.
So why not make GetFuel a function and pass the FuelCapacity in like #kcBeard states and return the Fuel value.
Private Sub Form1_Load() Handles MyBase.Load
Some Code
Fuel = DataProcesser.GetFuel(FuelCapacity)
End Sub
Public Shared Function GetFuel(Byval FuelCapacity as string) as string
Some Code
return og.Fuel.ToString() * FuelCapacity
End Function
You can make SpeedPref, FuelCapacity and Fuel public member variables, however a better approach would be to make them properties on the class with appropriate getters and setters. Dim just declares a variable. Please see the modified code sample below:
Form1.vb:
Namespace LFS_External_Client
Public Class Form1
Inherits Form
Private OutGauge As OutGaugeInterface
Private _SpeedPref As String
Private _FuelCapacity As String
Private _Fuel As String
Public Property SpeedPref
Get
return _SpeedPref
End Get
Set(value As String)
_SpeedPref = value
End Set
End Property
...
End Class
End Namespace
Related
I've put together this class so far but the last required step is to add a method that will display all of the practical info (I.E. the size, style and color) to the class itself.
I would typically just do this by setting up and calling a module outside of the class but for this project I am not aloud to do so.
Here's what I've got so far (I don't have the module main or any other modules set up just yet as I am hung up on this particular issue):
Class Sweater
Private Real sweaterSize
Private String sweaterStyle
Private String sweaterColor
Public Module Sweater()
Set sweaterSize = 0
Set sweaterStyle = " "
Set sweaterColor = " "
End Module
Public Module Sweater(Real newSweaterSize, String newSweaterStyle, String
newSweaterColor)
Set sweaterSize = newSweaterSize
Set sweaterStyle = newSweaterStyle
Set sweaterColor = newSweaterColor
End Module
Public Module setSweaterSize(Real newSweatersize)
Set sweaterSize = newSweaterSize
End Module
Public Function Real getSweatersize()
Return sweaterSize
End Function
Public Module setSweaterStyle (String newSweaterStyle)
set sweaterStyle = newSweaterStyle
End Module
Public Function String getSweaterStyle()
Return sweaterStyle
End Function
Public Module setSweaterColor (String newSweaterColor)
set sweaterColor = newSweaterColor
End Module
Public Function String getSweaterColor()
Return sweaterColor
End Function
You should just be able to create another public function inside the class that calls your accessor methods or the variables themselves. For example
Public Function null display()
Display getSweaterSize()
Display getSweaterStyle()
Display getSweaterColor()
End Function
I have a viewmodel and it exists out of entity framework classes (just plain classes). I Read on stackoverflow that it's okey to put an inotifypropertychanged in the model. So I did that in order not to have a lot of extra code.
So, now I have to perform an action when a property changes in one of my list items... the thing is, I can't react on this, in my viewmodel...
What do I do?
I have come across this issue once I started making larger projects with the MVVM pattern.
In the end I just shifted my INotifyPropertyChanged event calls to the ViewModel properties. I also decorated these properties with validation notification as that is where most of the validation that needs a user to react to will be held, any common elements can also be pulled out to a base ViewModel where relevant.
Another issue that you might come across as time goes by is where to put some of your processing logic. I used to have mine at the Model level, but then some of them required a bit closer interaction with the UI (validation reasons mainly), but if I put it in the ViewModel then I would have to have references to my repositories etc. In the end my ViewModels have access to another layer (a Service Layer) where this takes place. (A prime example for the use of this would be if you have a column in a database which is unique that you need to check when a user has created/modified data belonging to this column.)
Anyway, that is just a bit of extra information that I had to figure out shortly after the issue your currently having!
i fought with the best stategy for this for a while. I found that there are a number of different ways to do this.
First thing to note, if you add the property validation/notification directly to your model classes then the notifictaion and validation will happen when the class is created and for each object that gets created in observable collections, which in turn can cause performance issues or other challenges. So for that reason I moved my validation and notification into a "helper" partial class for the model.
So the model gets created through the Entity framework, lets say for an object called Job. I create public partial class called job as well. Here is an example (in vb, I can convert to C# if you need)
Partial Public Class job
Inherits ValidationBase
#Region "CONSTRUCTORS"
Public Sub New()
''default values
Me.FTC_Type = 4
Me.dtCreated = Now
Me.dtUpdated = Now
HasChanges = False
End Sub
Public Sub New(bValidate As Boolean)
PropertyValitaion(bValidate)
''default values
Me.FTC_Type = 4
Me.dtCreated = Now
Me.dtUpdated = Now
HasChanges = False
End Sub
Public ReadOnly Property DisplayPath
Get
Return "W" + idJob.ToString + ": " + chrTitle + " - " + client.chrCompany
End Get
End Property
Public ReadOnly Property SearchPath
Get
Return "W" + idJob.ToString + " " + chrTitle + " " + client.chrCompany + " " + chrContact
End Get
End Property
#End Region
#Region "VALIDATION FUNCTIONS"
Public Overrides Function Validate(validationContext As ComponentModel.DataAnnotations.ValidationContext) As IEnumerable(Of ComponentModel.DataAnnotations.ValidationResult)
Return MyBase.Validate(validationContext)
PropertyValitaion(True)
End Function
Public Sub PropertyValitaion(bAllProperties As Boolean, Optional sProperty As String = "")
'initialize validation helper
If bAllProperties OrElse sProperty = "chrTitle" Then
If String.IsNullOrEmpty(chrTitle) Then
AddError("chrTitle", "You must enter a Job Title")
Else
RemoveError("chrTitle")
End If
End If
End Sub
#End Region
End Class
So you can see that I can create other readonly properties (Like display title etc) and create my own custom validation that gets called when I want. THis validation uses the IDataErrorInfo for getting tied back into the UI. I have two constructors, one the calls the property validation and one that does not. That way I can control when it happens.
I created a ValidationBase class that my Objects partial class inhertis from. THis saves me from having to manually implement IdataErrorInfo and INotifyPropertyCHnaged in every partial class for every object.
Here is my validation base:
Imports System.ComponentModel
Imports System.Collections.Concurrent
Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema
Public Class ValidationBase
Implements IValidatableObject, IDataErrorInfo, INotifyPropertyChanged
#Region "DECLARATIONS"
Protected _propertyErrors As New Dictionary(Of String, String)
Protected _validationResults As New List(Of ValidationResult)
Public ReadOnly Property HasErrors() As Boolean
Get
Return (_propertyErrors.Count + _validationResults.Count) > 0
End Get
End Property
#End Region
#Region "IValidatableObject IMPLEMENTATION"
Public Overridable Function Validate(validationContext As ValidationContext) As IEnumerable(Of ValidationResult) Implements IValidatableObject.Validate
Return Nothing
End Function
#End Region
#Region "iDataError OBJECTS"
'Returns an error message
'In this case it is a general message, which is
'returned if the list contains elements of errors
Public ReadOnly Property [Error] As String Implements System.ComponentModel.IDataErrorInfo.Error
Get
If _propertyErrors.Count > 0 Then
Return "Object data is invalid"
Else
Return Nothing
End If
End Get
End Property
Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
Get
If _propertyErrors.ContainsKey(columnName) Then
Return _propertyErrors(columnName).ToString
Else
Return Nothing
End If
End Get
End Property
#End Region
#Region "IDataError FUNCTIONS"
'Adds an error to the collection, if not already present
'with the same key
Protected Sub AddError(ByVal columnName As String, ByVal msg As String)
If Not _propertyErrors.ContainsKey(columnName) Then
_propertyErrors.Add(columnName, msg)
OnPropertyChanged(columnName)
End If
End Sub
'Removes an error from the collection, if present
Protected Sub RemoveError(ByVal columnName As String)
If _propertyErrors.ContainsKey(columnName) Then
_propertyErrors.Remove(columnName)
OnPropertyChanged(columnName)
End If
End Sub
Public Sub ClearErrors()
_propertyErrors.Clear()
End Sub
#End Region
#Region "INotifyPropertyChanged IMPLEMENTATION"
Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
Public Overridable Sub OnPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
#End Region
End Class
SO i can't say this is the totally right way because there does not seem to be a clear best pratcie defined out there. But this works for me and I hope it can help you.
What's the right way to run a EF6 stored procedure (database-first) in async mode?
I read about ToListAsync() but I don't see that available on stored procedure.
Also not sure if there is a different way to call the stored procedure when the actual call returns (#1) an OUT param or a (#2) list of items:
Case #1
using (DBContext db = new DBContext())
{
ObjectParameter result = new ObjectParameter("Result",
typeof(global::System.Boolean));
db.Login("email#email.com", "password", result);
}
Case #2
using (DBContext db = new DBContext())
{
var result = db.Contact_GetList("New York");
}
Thanks for the help
As per this workitem you would need to use SqlQueryAsync. Feel free to upvote the work item on the EF Codeplex site.
To map stored procedures and start using it with out writing any initial code, this is how I did it.
create a new model with a new connection string that will generate the connection string automatically in the web.config file where the connection string is at (if you use a current connection string it may no work when you test the function for the SP on the model browser).
map your table and the stored procedures (you can test the stored procedures in the model browser).
create classes that represents the attributes retrieved by each stored procedure e.g if your stored procedure returns three columns A,B,C, then the class must also have these three columns as attribute with the [key()] on top of the column that is going to be the PK
now create your controller with the class created and a new DbContext
then copy the information in the data context generated for the model and pasted in the new context that you generate when creating the controller.
when you want to use the store procedures they will be ready on the db.context because you paste their code on you new db-context that you create when the controller was crated.
NOTE: I hope this is not confusing but I can use the stored procedures with out typing any code, please ask me if you need sample code or screen shots, your new db-context will not over write after you created
This is the stored procedure I map
'--------------------------------------------------------------------------
' <auto-generated>
' This code was generated from a template.
'
' Manual changes to this file may cause unexpected behavior in your application.
' Manual changes to this file will be overwritten if the code is regenerated.
' </auto-generated>
'-----------------------------------------------------------------------
Imports System
Imports System.Collections.Generic
Partial Public Class phone_CurrentConferences_Result
Public Property AppointmentID As Integer
Public Property AppTitle As String
Public Property DateTime As Nullable(Of Date)
Public Property [Date] As String
Public Property Time As String
Public Property Company As String
Public Property Contact As String
Public Property Phone As String
Public Property Office As String
Public Property Lead_Director As String
Public Property TBD As Nullable(Of Boolean)
Public Property conference As String
End Class
This is the same model with a primary key
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel.DataAnnotations
Public Class Conferences
[Key]
Public Property AppointmentID As Integer
Public Property AppTitle As String
Public Property DateTime As Nullable(Of Date)
Public Property [Date] As String
Public Property Time As String
Public Property Company As String
Public Property Contact As String
Public Property Phone As String
Public Property Office As String
Public Property Lead_Director As String
Public Property TBD As Nullable(Of Boolean)
Public Property conference As String
End Class
This is the context generated by the EF
'--------------------------------------------------------------------------
' <auto-generated>
' This code was generated from a template.
'
' Manual changes to this file may cause unexpected behavior in your application.
' Manual changes to this file will be overwritten if the code is regenerated.
' </auto-generated>
'--------------------------------------------------------------------------
Imports System
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Data.Entity.Core.Objects
Imports System.Linq
Partial Public Class DayMasterEntities
Inherits DbContext
Public Sub New()
MyBase.New("name=DayMasterEntities")
End Sub
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
Throw New UnintentionalCodeFirstException()
End Sub
Public Overridable Function phone_CurrentConferences(number As String, [date] As Nullable(Of Date)) As ObjectResult(Of phone_CurrentConferences_Result)
Dim numberParameter As ObjectParameter = If(number IsNot Nothing, New ObjectParameter("number", number), New ObjectParameter("number", GetType(String)))
Dim dateParameter As ObjectParameter = If([date].HasValue, New ObjectParameter("date", [date]), New ObjectParameter("date", GetType(Date)))
Return DirectCast(Me, IObjectContextAdapter).ObjectContext.ExecuteFunction(Of phone_CurrentConferences_Result)("phone_CurrentConferences", numberParameter, dateParameter)
End Function
End Class
SO, when I create the controller I use the model with the <KEY()> and I create my own context that will look like this
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Data.Entity.Core.Objects
Namespace Models
Public Class DayMasterContext
Inherits DbContext
' You can add custom code to this file. Changes will not be overwritten.
'
' If you want Entity Framework to drop and regenerate your database
' automatically whenever you change your model schema, please use data migrations.
' For more information refer to the documentation:
' http://msdn.microsoft.com/en-us/data/jj591621.aspx
Public Sub New()
MyBase.New("name=DayMasterEntities")
End Sub
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
Throw New UnintentionalCodeFirstException()
End Sub
Public Property Conferences As System.Data.Entity.DbSet(Of Conferences)
End Class
End Namespace
Then I copy the info in the context generated by the EF to my context
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Data.Entity.Core.Objects
Namespace Models
Public Class DayMasterContext
Inherits DbContext
' You can add custom code to this file. Changes will not be overwritten.
'
' If you want Entity Framework to drop and regenerate your database
' automatically whenever you change your model schema, please use data migrations.
' For more information refer to the documentation:
' http://msdn.microsoft.com/en-us/data/jj591621.aspx
Public Sub New()
MyBase.New("name=DayMasterEntities")
End Sub
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
Throw New UnintentionalCodeFirstException()
End Sub
Public Overridable Function phone_CurrentConferences(number As String, [date] As Nullable(Of Date)) As ObjectResult(Of phone_CurrentConferences_Result)
Dim numberParameter As ObjectParameter = If(number IsNot Nothing, New ObjectParameter("number", number), New ObjectParameter("number", GetType(String)))
Dim dateParameter As ObjectParameter = If([date].HasValue, New ObjectParameter("date", [date]), New ObjectParameter("date", GetType(Date)))
Return DirectCast(Me, IObjectContextAdapter).ObjectContext.ExecuteFunction(Of phone_CurrentConferences_Result)("phone_CurrentConferences", numberParameter, dateParameter)
End Function
Public Property Conferences As System.Data.Entity.DbSet(Of Conferences)
End Class
End Namespace
So, now you can use this context to query
entConferences(number As String, [date] As Nullable(Of Date)) As ObjectResult(Of phone_CurrentConferences_Result)
or to get a DBSet(of conferences)
Here is a controller I have created with this technique
Look where I call my stored procedure
Dim conferences = db.phone_CurrentConferences(phoneNumber, currentDate)
Imports System.Data
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Linq
Imports System.Net
Imports System.Net.Http
Imports System.Web.Http
Imports System.Web.Http.Description
Imports BIWEBAPI
Imports BIWEBAPI.Models
Namespace Controllers.DayMasterControllers
Public Class ConferencesController
Inherits System.Web.Http.ApiController
Private db As New DayMasterContext
' GET: api/Conferences
Function GetConferences() As IQueryable(Of Conferences)
Return db.Conferences
End Function
' GET: api/Conferences/3053742500
''' <summary>
''' Use to get the current conferences selected by date
''' </summary>
''' <param name="id">phone number and date separated by coma ",""</param>
''' <returns>conferences by date</returns>
''' <remarks></remarks>
<ResponseType(GetType(Conferences))>
Function GetConferences(ByVal id As String) As List(Of Conferences)
Dim conferencelist = New List(Of Conferences)
Dim dateAndPhoneNumber = Split(id, ",")
Dim currentDate = ""
Dim phoneNumber = dateAndPhoneNumber(0)
If dateAndPhoneNumber.Length > 1 Then
currentDate = DateTime.Parse(dateAndPhoneNumber(1))
Else : currentDate = DateTime.Today
End If
Dim conferences = db.phone_CurrentConferences(phoneNumber, currentDate)
For Each conferenceInQuery As Object In conferences
Dim conference = New Conferences()
conference.AppointmentID = conferenceInQuery.AppointmentID
conference.AppTitle = conferenceInQuery.AppTitle
conference.DateTime = conferenceInQuery.DateTime
conference.[Date] = conferenceInQuery.[Date]
conference.Time = conferenceInQuery.Time
conference.Company = conferenceInQuery.Company
conference.Contact = conferenceInQuery.Contact
conference.Phone = conferenceInQuery.Phone
conference.Office = conferenceInQuery.Office
conference.Lead_Director = conferenceInQuery.Lead_Director
conference.TBD = conferenceInQuery.TBD
conference.conference = conferenceInQuery.conference
conferencelist.Add(conference)
Next
Return conferencelist
End Function
' PUT: api/Conferences/5
<ResponseType(GetType(Void))>
Function PutConferences(ByVal id As Integer, ByVal conferences As Conferences) As IHttpActionResult
If Not ModelState.IsValid Then
Return BadRequest(ModelState)
End If
If Not id = conferences.AppointmentID Then
Return BadRequest()
End If
db.Entry(conferences).State = EntityState.Modified
Try
db.SaveChanges()
Catch ex As DbUpdateConcurrencyException
If Not (ConferencesExists(id)) Then
Return NotFound()
Else
Throw
End If
End Try
Return StatusCode(HttpStatusCode.NoContent)
End Function
' POST: api/Conferences
<ResponseType(GetType(Conferences))>
Function PostConferences(ByVal conferences As Conferences) As IHttpActionResult
If Not ModelState.IsValid Then
Return BadRequest(ModelState)
End If
db.Conferences.Add(conferences)
db.SaveChanges()
Return CreatedAtRoute("DefaultApi", New With {.id = conferences.AppointmentID}, conferences)
End Function
' DELETE: api/Conferences/5
<ResponseType(GetType(Conferences))>
Function DeleteConferences(ByVal id As Integer) As IHttpActionResult
Dim conferences As Conferences = db.Conferences.Find(id)
If IsNothing(conferences) Then
Return NotFound()
End If
db.Conferences.Remove(conferences)
db.SaveChanges()
Return Ok(conferences)
End Function
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If (disposing) Then
db.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Private Function ConferencesExists(ByVal id As Integer) As Boolean
Return db.Conferences.Count(Function(e) e.AppointmentID = id) > 0
End Function
End Class
End Namespace
I've searched for a bit, but I couldn't find a similar enough question/answer. So here it goes:
I have a class object called Project. A Project can have multiple Scenarios assoicated with it.
I've created the class modules for each object. But I am having difficulty in, I believe, instantiating the Scenarios collection for a given Project.
Here are the class modules:
1) cProject:
Private pProjectID As Integer
Private pName As String
Private pDateCreated As String
Private pScenarios As cScenarios
' PROPERTIES
Public Property Get ProjectID() As Integer
ProjectID = pProjectID
End Property
Public Property Let ProjectID(value As Integer)
pProjectID = value
End Property
Public Property Get name() As String
name = pName
End Property
Public Property Let name(value As String)
pName = value
End Property
Public Property Get Scenarios() As cScenarios
Set Scenarios = pScenarios
End Property
Public Property Set Scenarios(value As cScenarios)
Set pScenarios = value
End Property
2) cScenarios collection class module:
Private pScenarios As Collection
Private Sub Class_Initialize()
Set pScenarios = New Collection
End Sub
Private Sub Class_Terminate()
Set pScenarios = Nothing
End Sub
Public Function Item(index As Variant) As cScenario
Set Item = pScenarios.Item(index)
End Function
Public Property Get Count() As Long
Count = pScenarios.Count
End Property
Public Sub Add(obj As cScenario)
pScenarios.Add obj
End Sub
Public Sub Remove(index As Variant)
pScenarios.Remove index
End Sub
And finally (3) the Scenario class object:
Private pScenarioID As Integer
Private pName As String
Private pDateCreated As String
Private pParent As cProject
Public Property Get ScenarioID() As Integer
ScenarioID = pScenarioID
End Property
Public Property Let ScenarioID(value As Integer)
pScenarioID = value
End Property
Public Property Get name() As String
name = pName
End Property
Public Property Let name(value As String)
pName = value
End Property
Public Property Get parent() As cProject
parent = pParent
End Property
Public Property Let parent(value As cProject)
pParent = value
End Property
Here is a standard module:
Sub test1()
Dim cS As cScenarios
Dim s As cScenario
Set cS = New cScenarios
For i = 1 To 3
Set s = New cScenario
s.name = "s" & i
cS.Add s
Next
Debug.Print cS.Item(3).name
Debug.Print cS.Count
End Sub
This works. All is good. For now. I am able to populate cS with multiple scenarios. However, if I reference the scenarios collection as a child object of the project (see below in test2() ), I get a "Run-time error '91': Object variable or With block variable not set" triggered on the cs.Add call.
Sub test2()
Dim p As cProject
Dim cS As cScenarios
Dim s As cScenario
Set p = New cProject
Set cS = p.Scenarios
For i = 1 To 3
Set s = New cScenario
s.name = "s" & i
cS.Add s
Next
Debug.Print cS.Item(3).name
Debug.Print cS.Count
End Sub
What did I do wrong building my class modules and/or how do I fix it? Thanks.
You are not initializing pScenarios in the cProject class before trying to access it with Add().
You can fix that by adding an initializer to cProject:
Private Sub Class_Initialize()
Set pScenarios = New cScenarios
End Sub
This will guarantee that the cS instance will not be Nothing when you try to invoke Add on it inside test2.
Another way (weaker IMO) would be to set p.Scenarios = new cScenarios after newing up p inside test2.
Also, make sure that the property setter for cScenario.parent is Property Set instead of Property Let.
How can I return a different value for MyList using Moles?
Given the following class:
Namespace Test
Public Class MyTestClass
Private Sub New()
End Sub
Public Shared ReadOnly MyList As New List(Of String)({"SomeValue"})
End Class
End NameSpace
I've tried to access the shared property from Test.Moles.MMyTestClass but MMyTestClass doesn't contain the member MyList. I also tried to add a behavior to return the value I want, but again, I'm not sure how to access the MyList from the test method.
Thanks!