Tricky VB to C# conversion

  • Thread starter meerkatinfrance
  • Start date
M

meerkatinfrance

I am trying to convert some VB that uses Linq into C#
Is there anyone out there who is kind enough (clever enough) to show
me how to convert the following Sub loadAddress into C# for me.

Sub DoIt()
Dim WWV5 As New WWV5DataContext
Dim Xorg As Object

If Roles.IsUserInRole("Admin") Then
Xorg = (From o In WWV5.ORGs Where o.OrgID = ID Select o).Single
Else
Xorg = (From o In WWV5.ORGScopies Where o.OrgID = ID Select o).Single
End If
loadAddress(Xorg)
End Sub

Protected Sub loadAddress(ByRef pOrg As Object)
txtName.Text = pOrg.OrgName
txtCharNum.Text = pOrg.CharNum
txtAdd1.Text = pOrg.Add1
End Sub
 
M

Marc Gravell

This is complicated because it appears that the VB is using "Option
Explicit Off" or "Option Strict Off" (I'm nto really a VB-person, so
I'm not sure which ;-p) - i.e.
Protected Sub loadAddress(ByRef pOrg As Object)
txtName.Text = pOrg.OrgName
...

I C# you can't do this; you'd need to declare pOrg as something more
specific; I'm guessing that there is a suitable type here - possibly
"Org" or something (not clear from the code); basically, whatever Xorg
really is. If "ORGs" and "ORGscopies" return completely different
types, you may need to use a common interface, but I'm guessing that
they return the same type.

Once you've typed XOrg and pOrg correctly, the rest should be simple -
something like:

Org org;
if(Roles.IsUserInRole("Admin")) {
org = (from o in WWV5.ORGs where o.OrgID == ID select o;).Single();
} .. etc
LoadAddress(org);

protected void LoadAddress(Org org) {
txtName.Text = org.OrgName;
// etc
}

Note I dropped the "ByRef" since it is unnecessary even in the VB: you
aren't reassigning the instance.

Actually, for very simple uses like above, I tend to find the
"regular" syntax clearer than the LINQ syntax; I'd be inclined to
write:

org = WWV5.ORGs.Where(o => o.OrgID == ID).Single();

Marc
 
M

Marc Gravell

Oh; one other thing; data contexts are usually disposable, so I'd
actually have something like:

using(var ctx = new WWV5DataContext()) {
Org org;
if(Roles.IsUserInRole("Admin")) {
org = ctx.ORGs.Where(o=>o.OrgID == ID).Single();
} else {
org = ctx.ORGScopies.Where(o=>o.OrgID == ID).Single();
}
LoadAddress(org);
}
 
M

meerkatinfrance

Hi Marc.
Thankyou so much for your reply.
I have noted your recommendations and will use them in future.

It is clear that you know what you are talking about, so I am
embarrassed to admit that I could not find your solution.

Either it is staring me in the face or I did not explain the problem
correctly.

You are right - Orgs and OrgsCopy are two Identical SQL database
tables ( the data in them is obviously different)

You say that I need to declare something more specific ( not use
object )
The only way I can think of doing this would be to have the following,
but that defeats the object of having a common LoadAddress()

Are you saying I have to do this? I hope not, because that would mean
C# would be impractical. This would be a huge shame, because I was
getting to like it :-(


void getdata(string UserName, int ID)
{
WWV5DataContext WWV5 = new WWV5DataContext();

if (UserName == "Admin")
{
ORG Xorg = WWV5.ORGs.Where(o => o.OrgID == ID).Single();
LoadAddressOrg(Xorg);
}
else
{
ORGScopy Xorg = WWV5.ORGScopies.Where(o => o.OrgID ==
ID).Single();
LoadAddressOrgsCopy(Xorg);
}
}

void LoadAddressOrg(ORG Xorg)
{
txtName.Text = Xorg.OrgName;
txtAddress.Text = Xorg.Add1;
}

void LoadAddressOrgsCopy(ORGScopy Xorg)
{
txtName.Text = Xorg.OrgName;
txtAddress.Text = Xorg.Add1;
}
 
M

meerkatinfrance

Hello Marc,

Me again !
I forgot to mention that the using statement you suggestion did not
work. error:Cannot implicitly convert type 'ORGScopy' to 'ORG'

I hope you have not gone home :)

Regards,

Pete
 
M

Marc Gravell

I forgot to mention that the using statement you suggestion did not
work.  error:Cannot implicitly convert type 'ORGScopy' to 'ORG'

OK; sounds like my assumption (that they were the same type) was
wrong. Not to worry. There are a few more tricks we can use - the
first is an interface:

public interface IOrg {
string OrgName {get;}
string CharNum {get;}
string Add1 {get;}
}

This says "there is an interface IOrg, that has a few readable named
properties".

Now; if you make LoadAddress accept an IOrg, it should still compile.
The next trick is to make both ORG and ORGScopy implement this
interface. Luckily, partial classes and implicit implementation come
to our rescue. The following additional code should suffice (must be
in the same namespace as you ORG etc):

partial class ORG : IOrg {}
partial class ORGScopy : IOrg {}

This says "here's some extra code for ORG: it implements IOrg"; the
implementations should be found automatically.

Finally we need to ensure that the compile knows what we are doing, so
we change the first line here:

IOrg org;
if(Roles.IsUserInRole("Admin")) {
org = ctx.ORGs.Where(o=>o.OrgID == ID).Single();
} else {
org = ctx.ORGScopies.Where(o=>o.OrgID == ID).Single();
}
LoadAddress(org);

See how that goes ;-p

Any problems, post back...
 
M

meerkatinfrance

Hi Marc,

I must admit that I was a bit sceptical when I first read your
messsage but I desparately needed this thing to work.

I have not the faintest idea what an Interface is ( but I will now
learn ).
Instead of creating the partial classes you suggested, I just added
the Interface to the end of the ORG and ORGScopy classes of the dbml
file

public partial class ORG : INotifyPropertyChanging,
INotifyPropertyChanged, IOrg

public partial class ORGScopy : INotifyPropertyChanging,
INotifyPropertyChanged, IOrg

I copied the rest of your suggestion to the letter, and all worked
perfectly, although I have no idea why.

I am extremely happy - thank you very much for taking the time to
help.

I can't thank you enough,

Regards,

Pete
 
M

Marc Gravell

I just added the Interface to the end of the ORG and ORGScopy classes
of the dbml file

*important*:

You shouldn't edit the generated code (from the dbml) - it is quite
likely (i.e. guaranteed) to be randomly destroyed when the compiler
decides it wants to update the generated class files.

Partial classes are simply a way of getting around this, by separating
the /user/ code and the /generated/ code into separate files. Hence
the "partial" bit I quoted does exactly the same as adding ": IOrg" to
the generated class, but without the risk of losing your change at the
worst possible moment.
(interfaces)

Interfaces are a way of describing the signature of an object, without
having to know the implementation details. In particular, it allows us
to describe the common features of ORG and ORGScopy (i.e. that they
both have a few properties such as OrgName), without forcing them to
be the same thing. I'm probably not describing it right; I recommend
finding a good "OO" book?
thank you very much for taking the time to help.

You are more than welcome; I'm glad it worked ;-p
If you get any problems, post back (but you might want to start a new
topic if it is an unrelated issue).

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

VB to c# conversion... 4
VB to C# help 4
vb to c# conversion 5
Converting VB to C# 4
converting VB codes to C# 3
VB to C# conversion ODBC 8
Converting From VB.Net or C# to VBA 7
This C# code to VB 2

Top