VB Auto Implemented Property not compiling - vb.net

After quite some frustrating research into VB auto properties. I decided to just ignore them. So I had this code.
Public Class Categoria
Private _nome As String
Public ReadOnly Property Nome As String
Get
Return _nome
End Get
End Property
Public Sub New(nome As String)
Me._nome = nome
End Sub
End Class
But Visual Studio, being helpful, suggested to use auto-properties. I agreed, I even tried that before but he offered help in the form of a click here and I will do it. So I did. And he did exactly the same code I was not having any luck with before, char by char.
Public Class Categoria
Public ReadOnly Property Nome As String
Public Sub New(nome As String)
Me.Nome = nome
End Sub
End Class
Can someone shed some light as to why the last piece of code fails to compile with error BC30126: 'ReadOnly' property must provide a 'Get'.?
Aparently VS is missing the same as I am, so I don't feel so stupid anymore.

As point out by #Heinzi and following a previous post he supplied.
How can I use the latest VB.NET language level in an ASP.NET web site project?
Updating the Microsoft.CodeDom.Providers.DotNetCompilerPlatform NuGet package fix it, in my dev machine at least.

Related

My.User.IsInRole() is not working after migrating to 4.6.2 framework in vb.net

Currently i'm working in one migration request, where we need to change the framework from 3.5 to 4.6.2. Here the problem is after changing the framework below method is not showing result as expected.
My.User.IsInRole() is returning null.
Could anyone please suggest equivalent code for the above or please suggest steps to resolve the issue in my Visual Studio.
Earlier I faced problem with My.User.Name and changed the code to Environment.Username but for this I am unable to find some alternate method.
My.User.IsInRole() should not return null/Nothing. The return value is a Boolean.
As an alternative you can use System.Security.Principal Namespace like in the following example:
Imports System.Security.Principal
Class PrincipalCheck
Shared Function UserInRole(role As String) As Boolean
Dim currPrincipal As New WindowsPrincipal(New WindowsIdentity(Environment.UserName))
Return currPrincipal.IsInRole(role)
End Function
End Class
Public Sub StartCheck()
MsgBox(PrincipalCheck.UserInRole("MyDomain\MyGroup"))
End Sub
But this should return the same result:
MsgBox(My.User.IsInRole("MyDomain\MyGroup"))

Linq to Sql navigation object instance properties are null or default

I'm using Linq to Sql and have a proper foreign key relationship setup in the underlying tables.
However, when I try to use navigation properties I have a subtle bug.
In the code sample below, when I put a watch on the PartDetails, I do get the fully populated parts. However, if I call the property on each part to check their values, the instance is now null.
I've hunted around for the last couple of hours to find an answer but so far coming up dry.
Can anyone clue me in as to why this is happening?
I'm on .net 4.6.1, Visual studio 2015 and Sql Server 2014.
I confess I couldn't find the correct place to fire off the DataLoadOptions but this seemed to work fine!
Partial Public Class LabourDetail
Private Sub OnCreated()
Dim db As New DataContext
Dim ds As DataLoadOptions = New DataLoadOptions()
ds.LoadWith(Function(c As LabourDetail) c.PartDetails)
db.LoadOptions = ds
End Sub
Public ReadOnly Property AnyPartsUnConsumed As Boolean
Get
'If I put a watch on the partdetails I do get a proper collection with proper instances.
Return PartDetails.Where(Function(p) p.PartsUnConsumed).Any
End Get
End Property
End Class
Partial Public Class PartDetail
'When we reach this point, the values in the instance are all Null / Default
Public Property PartsUnConsumed() As Boolean = _CheckPartsUnConsumed()
End Class
I'd be grateful for any assistance!
This Private Sub OnCreated() effectively doesn't do anything. It creates a context that immediately goes out of scope.
I assume there is some context that materializes LabourDetails from the database. That's the context to set the LoadOptions of.

Modifiy the default auto implement "template" in VB.net 2015

in a class i declare a variable private :
Private test As String
then i right click do quick action and generate :
Public Property Test1 As String
Get
Return test
End Get
Set(value As String)
test = value
End Set
End Property
Do you know a way to modify the autogenerate code produce?
I want to add something like :
Public Property Test1 As String
Get
Return test
End Get
Set(value As String)
Tmp_Val = test
test = value
RaiseEvent VariableChanged(test, Tmp_Val, VarDesc("test"))
End Set
End Property
if somebody know a place where the "template" is stored?
Thanks.
quick actions are used for refactoring and pointers toward fixing errors in your code, not so much for automatic code generation. Unfortunately, I haven't found any way to edit these. You can however edit code snippets, but this is laborious to say the least. There is an extension you can install which is supposed to make snippet editing easier - I haven't tried it, but it comes via Microsoft#s Visial Studio Gallery -
Snippetizer

VB.NET: no warning when returning object that is not an instance of function's return type

We have this:
Friend NotInheritable Class ConcreteGraphFactory
Inherits AbstractGraphFactory
Public Shared ReadOnly Instance As New ConcreteGraphFactory()
Private Sub New()
MyBase.New()
End Sub
Friend Overrides Function Create() As AbstractGraph
Return New ConcreteGraph()
End Function
Private NotInheritable Class ConcreteGraph
Inherits AbstractGraph
Private ReadOnly Question1 As New Question("Why isn't this showing a warning?")
Public Overrides Function GetRoot() As IRoot
Return Question1 '<---HERE
End Function
Public Sub New()
End Sub
End Class
End Class
And I have IRoot:
Friend Interface IRoot
Inherits IQuestion
Function GetContainer() As AbstractGraph
End Interface
And finally Question:
Public Class Question
Implements IQuestion
' code....
End Class
Why would VS not show a warning? Question does not implement IRoot...
If you want the compiler to give an error there, then you need to set Option strict to On. You can do that on the Compile tab of the project's Properties. Or add Option Strict On to the top of the file that contains this code.
Here are a few pages that have more details about what Option Strict means.
http://support.microsoft.com/en-us/kb/311329
https://msdn.microsoft.com/en-us/library/zcd4xwzs.aspx
Option Strict Off means that the Visual Basic compiler doesn't enforce strict data typing. It will try to do implicit type conversions and throw run time errors if that can't be done.
I didn't think it had anything to do with IRoot being an interface, but after trying it out it looks like it does. If GetRoot returned a class that Question didn't inherit from, then you would get a compiler error even with Option Strict off.
Running with Option Strict off actually makes some things easier, especially when dealing with late bound COM objects. For the most part, you don't have to worry about type casts when writing code.
However, it's also one of the reasons many people don't like VB.NET. Personally, I liked it when I was working with it, but it's been long enough now that it does seem strange that the compiler wouldn't be doing all the strict type checking for you. I could always tell when some VB code had been generated via a conversion tool from C# because it would have a bunch of DirectCast calls that you wouldn't see in code that a VB developer had written.
When C# came out with the dynamic keyword in 2009, the VB.NET developers were thinking, "Meh. We've always been able to write code without worrying about types." Of course, VB.NET wasn't the same as dynamic in C#, but many of the early dynamic code examples were showing things that you could already do in VB with option strict turned off.

Expose .NET DataTable properties to VBA via COM Interface

I am trying to create a .Net DLL basically as an abstraction layer for database connections; it is going to replace a current DLL we have that is written in VB6 and I am trying to match the current functionality as much as possible.
Anyway, the essential issue I am having is that I can't find a way to get .Net classes like DataColumnCollection or DataColumn to display in the VBA Interpreter -- It may say, for example, "Column" with the type "MarshalByValueComponent," but the value will be "No Variables".
I can get it to work if I completely re-create both classes (i.e. Fields as a collection of field, which inherits from DataColumn, and then define an interface for both), but that seems like a lot of added overhead for what (should be?) a pretty simple idea. I feel like I am just missing something very simple with the way the marshaller is handling the DataColumn class.
A lot of the stuff I am finding online is on how to convert a DataTable or DataReader to a legacy ADODB Recordset, but that also would add a lot of overhead... I'd rather leave it as a DataTable and create a COM interface to allow VBA to interact with it; that way if, for example, they want to write the table to an excel sheet, I wouldn't be duplicating work (convert to ADODB recordset, then read/write to excel sheet. You'd need to iterate the entire table twice...)
Sorry for the book-length explanation -- I felt the problem needed a bit of clarification since the root-cause is trying to match legacy functionality. Here is an example of my current interface that does not work:
Public Interface IDataTable
ReadOnly Property Column As DataColumn
End Interface
<ClassInterface(ClassInterfaceType.None)> _
<System.ComponentModel.DesignerCategory("")> _
<ComDefaultInterface(GetType(Recordset.IDataTable))> _
<Guid("E7AFBBB6-CB20-44EC-9CD2-BC70B94CD8B7")> _
Public Class Recordset : Inherits Data.DataTable : Implements IDataTable
Public ReadOnly Property Column As DataColumn Implements IDataTable.Column
Get
Return MyBase.Columns(0)
End Get
End Property
Note: I originally tried the property Columns as DataColumnCollection which returned MyBase.Columns. That came through as an Object, instead of MarshalByValueComponent, but was also empty. I know MyBase.Column(0) has a value, because I can put Msgbox(MyBase.Columns(0).ColumnName) right above the return in the get and it pops up fine (don't judge; this is way easier than using a debugger for this)...
I wouldn't mind just defining them both, but I can't inherit DataColumnCollection and the COM interface already sucks at dealing with generics. Is there any other way around this without re-inventing the wheel?
Thanks for your help!
I just spent the last 3 weeks doing something eerily similar.
I ended up making two .NET assemblies:
A pure .NET assembly that talks to the datastore (for use by .NET apps).
A "COM Interop" assembly that wraps the first assembly and adds the COM overhead (ADODB references and COM-Visible interfaces).
I call the second assembly from Excel VBA using the VSTO "AddIn.Object" property.
I ended up converting System.Data.DataTables to ADODB.Recordsets as you mentioned. Getting .NET and VBA talking about anything other than primitive types was beyond-frustrating for me. In fact, I ended up serializing some objects as JSON so the two worlds could communicate.
It does seem insane, but I reinvented the wheel.
I followed this MSDN article to make my .NET code callable by VBA.
I used this Code Project article (I'm sure you've seen) to convert to Recordset*.
I let the frameworks handle string, integers, etc.
For all other data types I used Json.Net and a custom VBA class to do JSON serialization.
*Converted article to VB.Net and added some extra error handling.
Okay, this probably isn't the most elegant (or complete, at this point) solution; but I think it's the route I am going to go.
Instead of converting the whole thing to an ADODB Recordset (and duplicating any iterations), I just threw out the DataTable class entirely and wrote my own Recordset class as a COM Wrapper for the a generic Data Reader (via the IDataReader interface) and added a new Field class to manage the type conversion and set up Fields as an array of Field (since interop hates generics)
It basically creates a forward-only ADODB Recordset (same limitations) but has the benefit of only loading one row at a time, so the bulk of the data can be handled as managed code until you know what they want to do with it (I'm going to add methods for ToArray, ToAccessDB, ToFile, etc that use the reader) while still allowing the ability to iterate through the Recordset from excel/access/vbscript/vb6 (if that's really what they want to do.. mostly needed that for legacy support anyway)
Here is an example, in case anyone else has to do this again; somewhat modified for brevity:
Public Interface IRecordset
ReadOnly Property CursorPosition As Integer
ReadOnly Property FieldCount As Integer
ReadOnly Property Fields As Field()
Function ReadNext() As Boolean
Sub Close()
End Interface
<System.ComponentModel.DesignerCategory("")> _
<ClassInterface(ClassInterfaceType.None)> _
<ComDefaultInterface(GetType(IRecordset))> _
<Guid("E7AFBBB6-CB20-44EC-9CD2-BC70B94CD8B7")> _
Public Class Recordset : Implements IRecordset : Implements IDisposable
Private _Reader = Nothing
Private _FieldCount As Integer = Nothing
Private _Fields() As Field
Public ReadOnly Property CursorPosition As Integer Implements IRecordset.CursorPosition...
Public ReadOnly Property FieldCount As Integer Implements IRecordset.FieldCount...
Public ReadOnly Property Fields As Field() Implements IRecordset.Fields...
Friend Sub Load(ByVal reader As IDataReader)
_Reader = reader
_FieldCount = _Reader.FieldCount
_Fields = Array.CreateInstance(GetType(DataColumn), _FieldCount)
For i = 0 To _FieldCount - 1
_Fields(i) = New Field(i, Me)
Next
End Sub
'This logic kinda sucks and is dumb.
Public Function ReadNext() As Boolean Implements IRecordset.ReadNext
_EOF = Not _Reader.Read()
If _EOF Then Return False
_CursorPosition += 1
For i = 0 To _FieldCount - 1
_Fields(i)._Value = _Reader.GetValue(i).ToString
Next
Return True
End Function
From here you just need to define some type like Field or Column and add an interop wrapper for that type:
Public Interface IField
ReadOnly Property Name As String
ReadOnly Property Type As String
ReadOnly Property Value As Object
End Interface
<System.ComponentModel.DesignerCategory("")> _
<ClassInterface(ClassInterfaceType.None)> _
<Guid("6230C670-ED0A-48D2-9429-84820DC2BE6C")> _
<ComDefaultInterface(GetType(IField))> _
Public Class Field : Implements IField
Private Reader As IDataReader = Nothing
Private Index As Integer = Nothing
Public ReadOnly Property Name As String Implements IField.Name
Get
Return Reader.GetName(Index)
End Get
End Property
Public ReadOnly Property Value As Object Implements IField.Value
Get
Return Reader.GetValue(Index)
End Get
End Property
Public ReadOnly Property Type As String Implements IField.Type
Get
Return Reader.GetDataTypeName(Index).ToString
End Get
End Property
Sub New(ByVal i As Integer, ByRef r As IDataReader)
Reader = r
Index = i
End Sub
End Class
All of this is rather silly, but it seems to work well.
Note: I've only been using .Net for about 4 days now, so this might be terrible, please feel free to comment on anything extremely stupid I might be doing.