I need to verify if a certain user exist on my asp.net site.I want to know if which of these two functions is more efficient, faster and better compared to each other and why.Thanks in advance!
Public Function CheckIfFriendExist(ByVal arg As String) As Boolean
Dim alluser As New MembershipUserCollection()
alluser = Membership.GetAllUsers()
For Each user As MembershipUser In alluser
If user.UserName.ToLower() = arg.ToLower() Then
Return True
Exit For
End If
Next
Return False
End Function
or
Public Function CheckIFFriendExist2(ByVal arg As String) As Boolean
Dim x As Integer = 0
Dim themember As MembershipUserCollection = Membership.FindUsersByName(arg, 0, 1, 1)
For Each member As MembershipUser In themember
x = x + 1
Next
If x > 0 Then
Return True
Else
Return False
End If
End Function
First comment - get rid of the pointless instantiation when you declare allUser in your first block - change
Dim alluser As New MembershipUserCollection()
to
Dim alluser As MembershipUserCollection
It's impossible to answer the rest without knowing about the membership provider in user and the implementation of the method. Have you tried just timing it?
Generally speaking, the second option has the better potential for performance. The actual effect depends on which membership provider you are using, but in the second case any implementation can take advantage of any internal indexing mechanisms if they are present, and potentially less data needs to be retrieved and transferred because you're only getting at most one MembershipUser due to the paging.
Theoretically, the first option could be faster than the second, but that would mean the membership provider implementation really sucks :)
You appear to be counting the number of members in the collection, but you merely need to know if there is at least one member in the collection. Thus counting is not actually necessary. Also, what is wrong with using the Count property? I'm not saying this for optimization purposes since the impact will be minimal, but I think the intent of your code would be clearer if written that way.
Public Function CheckIFFriendExist2(ByVal arg As String) As Boolean
Dim foundMembers As MembershipUserCollection = _
Membership.FindUsersByName(arg, 0, 1, 1)
Return foundMembers.Count > 0
End Function
Alternatively, use Membership.GetUser to retrieve a single user by name. After all, I wouldn't recommend implementing a membership provider that allows for multiple users with the same name.
Which function is better in terms of readability:
I don't remember visual basic too well, but in the second function, isn't there a way to check themember to see whether it's empty directly, instead of having to loop through it? Some kind of method name like "IsEmpty".
Assuming that there is, you can change the code in the second example to just 2 lines:
Dim themember As MembershipUserCollection = Membership.FindUsersByName(arg, 0, 1, 1)
' Check if themember is empty, return true or false appropriately
In that case, the second function will be much better in the sense that it's easier to read.
Which function is better in terms of efficiency:
It's impossible to even guess without knowing the details of FindUsersByName or GetAllUsers, but I would guess the second function is faster (since it offloads the work to a specific function designed for it).
However, this is a very crude guess. The only proper way to answer this question is to implement the two and run tests on both, to find out which is faster.
In any case, the difference is unlikely to be enough to matter, but if you really care, you definitely have to time each solution.
Usually the easiest way to answer questions of this type ("which is faster"), is to simply measure it.
.NET har a built-in class for this purpose, System.Diagnostics.Stopwatch:
Dim stopwatch As New System.Diagnostics.Stopwatch
stopwatch.Start()
For i = 0 To 10000
MethodThatMightJustTakeTooLong()
Next i
stopwatch.Stop()
Console.Writeline(Elapsed)
I would go with the second function with a few modifications.
Instead of using FindUsersByName, try GetUser -- this is more correct as you are looking for one user.
Then, check the count property of the user.
Dim user = Membership.GetUser(arg)
If user = 1 Then
Return True;
Else
Return False;
End If
I don't really know Visual Basic, but I'm sure that if statement could be simpler, something like return (user === 1) ? true : false in other languages.
The performance of these functions are not going to make a noticeable difference until you have hundreds of thousands of users for the application.
My suggestion is to stop micro-optimizing unless you have identified this as a problem area through profiling.
Related
I was trying to do a little data access optimization, and I ran into a situation where a dictionary appeared to get out of sync in a way that should be impossible, unless I'm somehow getting into a multithreaded situation without knowing it.
One column of GridLabels binds to a property that does data access -- which is a tad expensive. However, multiple rows end up making the same call, so I should be able to head any problems off at the pass by doing a little caching.
However, elsewhere in the app, this same code is called in ways where caching would not be appropriate, I needed a way to enable caching on demand. So my databinding code looks like this:
OrderLabelAPI.MultiSyringeCacheEnabled = True
Me.GridLabels.DataBind()
OrderLabelAPI.MultiSyringeCacheEnabled = False
And the expensive call where the caching happens looks like this:
Private Shared MultiSyringeCache As New Dictionary(Of Integer, Boolean)
Private Shared m_MultiSyringeCacheEnabled As Boolean = False
Public Shared Function IsMultiSyringe(orderLabelID As Integer) As Boolean
If m_MultiSyringeCacheEnabled Then
'Since this can get hit a lot, we cache the values into a dictionary. Obviously,
'it goes away after each request. And the cache is disabled by default.
If Not MultiSyringeCache.ContainsKey(orderLabelID) Then
MultiSyringeCache.Add(orderLabelID, DoIsMultiSyringe(orderLabelID))
End If
Return MultiSyringeCache(orderLabelID)
Else
Return DoIsMultiSyringe(orderLabelID)
End If
End Function
And here is the MultiSyringeCacheEnabled property:
Public Shared Property MultiSyringeCacheEnabled As Boolean
Get
Return m_MultiSyringeCacheEnabled
End Get
Set(value As Boolean)
ClearMultiSyringeCache()
m_MultiSyringeCacheEnabled = value
End Set
End Property
Very, very rarely (unreproducably rare...) I will get the following exception: The given key was not present in the dictionary.
If you look closely at the caching code, that's impossible since the first thing it does is ensure that the key exists. If DoIsMultiSyringe tampered with the dictionary (either explicitly or by setting MultiSyringeCacheEnabled), that could also cause problems, and for awhile I assumed this had to be the culprit. But it isn't. I've been over the code very carefully several times. I would post it here but it gets into a deeper object graph than would be appropriate.
So. My question is, does datagridview databinding actually get into some kind of zany multithreaded situation that is causing the dictionary to seize? Am I missing some aspect of shared members?
I've actually gone ahead and yanked this code from the project, but I want to understand what I'm missing. Thanks!
Since this is ASP.NET, you have an implicit multithreaded scenario. You are using a shared variable (see What is the use of a shared variable in VB.NET?), which is (as the keyword implies) "shared" across multiple threads (from different people visiting the site).
You can very easily have a scenario where one visitor's thread gets to here:
'Since this can get hit a lot, we cache the values into a dictionary. Obviously,
'it goes away after each request. And the cache is disabled by default.
If Not MultiSyringeCache.ContainsKey(orderLabelID) Then
MultiSyringeCache.Add(orderLabelID, DoIsMultiSyringe(orderLabelID))
End If
' My thread is right here, when you visit the site
Return MultiSyringeCache(orderLabelID)
and then your thread comes in here and supercedes my thread:
Set(value As Boolean)
ClearMultiSyringeCache()
m_MultiSyringeCacheEnabled = value
End Set
Then my thread is going to try to read a value from the dictionary after you've cleared it.
That said, I am not sure what performance benefit you expect from a "cache" that you clear with every request. It looks like you should simply not make this variable shared- make it an instance variable- and any user request accessing it will have their own copy.
I've been doing some reading recently and have encountered the Law of Demeter. Now some of what I've read makes perfect sense e.g. the paperboy should never be able to rifle through a customers pocket, grab the wallet and take the money out. The wallet is something the customer should have control of, not the paperboy.
What throws me about the law, maybe I'm just misunderstanding the whole thing, is that stringing properties together with a heirarchy of functionality/information can be so useful. e.g. .NETs HTTPContext class.
Wouldn't code such as :
If DataTable.Columns.Count >= 0 Then
DataTable.Columns(0).Caption = "Something"
End If
Or
Dim strUserPlatform as string = HttpContext.Current.Request.Browser.Platform.ToString()
Or
If NewTerm.StartDate >= NewTerm.AcademicYear.StartDate And
NewTerm.EndDate <= NewTerm.AcademicYear.EndDate Then
' Valid, subject to further tests.
Else
' Not valid.
End If
be breaking this law? I thought (perhaps mistakenly) the point of OOP was in part to provide access to related classes in a nice heirarchical structure.
I like, for example, the idea of referencing a utility toolkit that can be used by page classes to avoid repetitive tasks, such as sending emails and encapsulating useful string methods:
Dim strUserInput As String = "London, Paris, New York"
For Each strSearchTerm In Tools.StringManipulation.GetListOfString(strUserInput, ",")
Dim ThisItem As New SearchTerm
ThisItem.Text = strSearchTerm
Next
Any clarity would be great...at the moment I can't reconcile how the law seems to banish stringing properties and methods together...it seems strange to me that so much power should be disregarded? I'm pretty new to OOP as some of you might have guessed, so please go easy :)
What the Law of Demeter (also "Law of Demeter for Functions/Methods") wants to reduce with saying "only use one dot" is that in a method you shouldn't have to assume such a lot of context from the provided arguments. This increases the dependency of the class and makes it less testable.
It doesn't mean that you can't use all of the above examples but it suggests that instead of giving your method the customer which then accesses the wallet and retrieves the money from it:
function getPayment(Customer customer)
{
Money payment = customer.leftpocket.getWallet().getPayment(100);
...
// do stuff with the payment
}
that you instead only pass what the paperboy needs to the method and as such reduce the dependency for the method if it's possible:
function getPayment(Money money)
{
// do stuff with the payment
}
Your benefit from it will be that you dont depend on the customer to have the wallet in the left pocket but instead just process the money the customer gives you. It's a decision you have to base on your individual case though. Less dependencies allow you to test easier.
I think applying the Law of Demeter to individual classes is taking it a bit too far. I think a better application is to apply it to layers in your code. For example, your business logic layer shouldn't need to access anything about the HTTP context, and your data access layer shouldn't need to access anything in the presentation layer.
Yes, it's usually good practice to design the interface of your object so that you don't have to do tons of property chaining, but imagine the hideously complex interface you'd have if you tried to do that to the DataTable and HttpContext classes you gave as examples.
The law doesn't say that you shouldn't have access to any information at all in a class, but that you should only have access to information in a way that you can't easily misuse it.
You can for example not add columns in a data table by assigning anything to the Count property:
DataTable.Columns.Count = 42;
Instead you use the Add method of the Columns object that lets you add a column in a way that all the needed information about the column is there, and also so that the data table get set up with data for that column.
''' <summary>
''' Returns true if a submission by the same IP address has not been submitted in the past n minutes.
'' </summary>
Protected Function EnforceMinTimeBetweenSubmissions(ByVal minTimeBetweenRequestsMinutes as Integer) As Boolean
If minTimeBetweenRequestsMinutes = 0 Then
Return True
End If
If Cache("submitted-requests") Is Nothing Then
Cache("submitted-requests") = New Dictionary(Of String, Date)
End If
' Remove old requests. '
Dim submittedRequests As Dictionary(Of String, Date) = CType(Cache("submitted-requests"), Dictionary(Of String, Date))
Dim itemsToRemove = submittedRequests.Where(Function(s) s.Value < Now).Select(Function(s) s.Key).ToList
For Each key As String In itemsToRemove
submittedRequests.Remove(key)
Next
If submittedRequests.ContainsKey(Request.UserHostAddress) Then
' User has submitted a request in the past n minutes. '
Return False
Else
submittedRequests.Add(Request.UserHostAddress, Now.AddMinutes(minTimeBetweenRequestsMinutes))
End If
Return True
End Function
No. The ASP.NET Cache is not inherently thread-safe and it looks like you are creating objects in the Cache depending on whether they exist or not.
You need to lock the Cache when writing to it.
Let me word things a little differently. The code is, in fact, thread safe. The way you currently have it coded though could cause performance issues in multi-threaded situations.
In this case, multiple users would be running the same code simultaneously, theoretically accessing and modifying the same cache objects at the same time. As that scenario scales up, performance suffers.
Creating a lock will improve performance under heavy load (while imposing a slight overhead under light load) because you won't be fetching data neadlessly due to Caching issues.
The System.Web.Caching.Cache class is thread-safe according to the MSDN documenation. However, the documenation also shows an example where a read and a write are performed on the cache without locking. That cannot possibily be thread-safe since the write is dependent on the read. The code you posted basically looks like the example. I definitely recommend putting a lock around the entire method.
just a simple question here. I've used Moq for awhile but, as of yet, have only used it for stubbing and not for mocking. I am trying to introduce our developers to unit testing. I set up a simple example to explain the concepts but i can't seem to get it working. Probably something simple so i thought i would just ask you all to see what i'm doing wrong:
<Test()> _
Public Sub Divide_DivideByZero_LogsError()
Dim mock = New Mock(Of ILogger)
With mock
Dim calc = New MyCalculator(New CalculatorData, .Object)
calc.Divide(55, 0)
.Verify(Function(x) CType(x,ILogger).WriteError(it.IsAny(of String),It.IsAny(Of String))))
End With
End Sub
I'm using Moq version 3.2.416.3. I get an error on the .verify telling me that i'm calling it with incorrect arguments. I'm just trying to verify that .WriteError was called. any help would be appreciated.
Edit:
Ok everyone, if i change ".WriteError" from a sub (void return) to a function that returns a boolean it works. WriteError doesn't really need to be a function. Does anyone know why a sub wouldn't work?
Edit: Ok everyone, if i change ".WriteError" from a sub (void return) to a function that returns a boolean it works. WriteError doesn't really need to be a function. Does anyone know why a sub wouldn't work?
As far, as I remember, VB9 does not support anonymous Subs (only Functions) and it's a serious show-stopper for Moq usage in VB.net.
So, as soon, as you have changed WriteError signature from Sub to Function, compiler have successfully resolved return type for anonymous function in Verify parametrer.
I think you need to make it Verifiable() before actually calling Verify(). I'm not sure if it can do automatic verifiability though.
And IMHO I find using VerifyAll() much easier than verifying individual methods. i.e.:
mock.Setup(Function(x) CType(x, ILogger).WriteError(It.IsAny(Of String), It.IsAny(Of String))) _
.Verifiable()
mock.Object.WriteError("test", "Test")
mock.VerifyAll()
Not sure if I get all the method names/signature right though but you should get the idea.
I find that in my daily Flex/Flash work, I do this number a lot:
//Calling a function...
MyCustomObject(container.getChildAt(i)).mySpecialFunction();
The question is - is this the best way to do this? Should I do this:
//Calling a function
var tempItem:MyCustomObject = container.getChildAt(i) as MyCustomObject;
tempItem.mySpecialFunction();
It might be incidental but I'm just wondering if there is an "accepted" way or a preferred way to do this. The second option seems more readable but I wonder if it takes more of a performance hit to create a new variable. Or does it all come down to style and preference?
It's important to remember that there is a difference between explicit casting and using the as keyword. Casting throws an error when it fails, whereas the as keyword does not (it just returns null).
// a casting error
try {
var number:int = 666;
var urlreq:URLRequest = URLRequest( number );
} catch(e:TypeError) {
// TypeError: Error #1034: Type Coercion failed: cannot
// convert 666 to flash.net.URLRequest.
trace(e);
}
Whereas the as keyword fails silently:
var number:int = 666;
var urlreq:URLRequest = number as URLRequest;
trace(urlreq); // prints null to the debug pane
Personally, I bear these behaviours in mind when deciding method to use. Generally, I'd recommend casting explicitly, as you'll know exactly how/when a cast failed. Often, though, you might want to fail silently and continue.
It generally doesn't matter. Creating a var just creates a pointer to the object, so it's not using more memory or anything like that.
The second example is definitely more readable and debuggable and should thus be preferred.
The risk you run from creating temp vars is that you might delay or prevent garbage collection for that object. This generally isn't a problem when it's just a local var in a function; just keep scope in mind when you're creating vars and passing them around.
For in-depth on the subject, read Grant Skinner's series on resource management in AVM2:
http://www.gskinner.com/blog/archives/2006/06/as3_resource_ma.html
for the second example you might want to test for the nullity to avoid a NullPointerException when invoking "mySpecialFunction", e.g.
var tempItem:MyCustomObject = container.getChildAt(i) as MyCustomObject;
if ( tempItem )
{
tempItem.mySpecialFunction();
}
I usually prefer the second approach but you have to remember that you can only use the as operator for casting "Date" and "Array" types.