Performance lack on delegate creation - c#

I have an app with repository pattern. It allows me to manipulate objects via LINQ, objects are stored in memory, so I can access them very fast. Here a sample code:
private Measurement ParseExact(AgentParameter agentParameter)
{
ControlledElement ce;
using (var repositoryBase = Datastore.GetRepository<ControlledElement>())
{
var mvId = Convert.ToInt32(agentParameter.ControlledParameterId);
var sId = Convert.ToInt32(agentParameter.FacilityId);
ce =
repositoryBase.Query(
t => t.FirstOrDefault(elem => elem.Sensor.Id == sId && elem.MeasuringValue.Id == mvId));
}
}
When I profiled my code with dotTrace I found that on high load I get a performance lack on creating delegate elem => elem.Sensor.Id == sId && elem.MeasuringValue.Id == mvId. My Query method looks like:
public TOut Query<TOut>(Func<IQueryable<TEntity>, TOut> specification) which means, that I really pass a Func<> object every time I use it. So, the question is, how can I optimize this?
EDIT proof of lack on creation and compilation

You can eliminate the compilation step by explicitly tracking the state in an object, rather than using a closure.
private Measurement ParseExact(AgentParameter agentParameter)
{
ControlledElement ce;
using (var repositoryBase = Datastore.GetRepository<ControlledElement>())
{
var mvId = Convert.ToInt32(agentParameter.ControlledParameterId);
var sId = Convert.ToInt32(agentParameter.FacilityId);
var query = new ParseExactQuery(mvId, sId);
ce = repositoryBase.Query(t => t.FirstOrDefault(query.Query));
}
}
private class ParseExactQuery {
private int mvId;
private int sId;
public ParseExactQuery (int mvId, int sId) {
this.mvId = mvId;
this.sId = sId;
}
public bool Query(ControlledElement elem) {
return elem.Sensor.Id == sId && elem.MeasuringValue.Id == mvId;
}
}

Related

Facebook api call - mutual friends - loop

I have this code which makes a call to Facebook API in order to get the mutual friends on the application for two given users. The parameter nextPage corresponds to facebook api's next page.
Problem is that although I have a limited number of common friends each time, I get errors from Facebook api, for having too many calls per second (about 5 milion/day overall). I tried mocking the call to facebook, to always return null, but that resulted in a CPU overloading due to w3p, with 99% usage. What am I missing?
public async Task<MutualFriendsModel> GetMutualFriends(Guid currentUserGuid,
Guid visitedUserGuid, string nextPage)
{
var currentUser = Get(currentUserGuid);
var visitedUser = _serviceUserLogin.GetByUserId(visitedUserGuid);
var mutualFriends = new MutualFriendsModel();
var hasNextPage = true;
while (hasNextPage && mutualFriends.Users.Count < 25)
{
var facebookResult = await
_facebookApi.GetMutualFriendsFacebookRequest(currentUser.Token,
visitedUser.ProviderKey, nextPage);
if (facebookResult == null) break;
mutualFriends.Update(facebookResult, this, _serviceUserLogin);
nextPage = mutualFriends.NextPageUrl;
hasNextPage = !string.IsNullOrEmpty(mutualFriends.NextPageUrl);
}
return mutualFriends;
}
Also, there is another variation of the above mentioned snippet, which only counts the mutual friends.
private async Task<IList<SavedCommentModel>> MutualFriendsCount(User currentUser,
IList<SavedCommentModel> comments)
{
var usersFriends = new Dictionary<Guid, long>();
foreach (var comment in comments)
{
if (usersFriends.ContainsKey(comment.UserId))
{
comment.TotalMutualFriends = usersFriends[comment.UserId];
}
else
{
var visitedUser = _serviceUserLogin.GetByUserId(comment.UserId);
if (visitedUser.LoginProvider != LoginProvider.Facebook.ToString()) continue;
var facebookResult = await
_facebookApi.GetMutualFriendsFacebookRequest(currentUser.Token, visitedUser.ProviderKey);
if (facebookResult == null) continue;
comment.TotalMutualFriends = facebookResult.Context.Mutual_friends.Summary.Total_Count;
usersFriends.Add(comment.UserId, comment.TotalMutualFriends);
}
}
return comments;
}

FluentValidation passing parameter

I've found FluentValidation only couple of hours ago and I want to rewrite all my validation logic so it will use only FV.
The issue that I have ATM is that I would like to use data coming from input as a parameter for DomainExists() method. Is it possible or do I have to figure out a way around FV to achieve that?
public QuoteValidator()
{
// hardcoded because don't know how to pass input string to RuleFor
var inputeddomain = "http://google.com";
RuleFor(r => r.Domain).NotEqual(DomainExists(inputeddomain));
}
// checks if inputeddomain is in repository (SQL DB)
private string DomainExists(string inputeddomain)
{
var context = new QuoteDBContext().Quotes;
var output = (from v in context
where v.Domain == inputeddomain
select v.Domain).FirstOrDefault();
if (output != null) { return output; } else { return "Not found"; }
}
Thanks to #bpruitt-goddard hint I got that to work. Here's a solution to my problem (hope it will help somebody).
public QuoteValidator()
{
RuleFor(r => r.Domain).Must(DomainExists).WithMessage("{PropertyValue} exists in system!");
}
private bool DomainExists(string propertyname)
{
var context = new QuoteDBContext().Quotes;
var output = (from v in context
where v.Domain == propertyname
select v.Domain).FirstOrDefault();
if (output != null) { return false; } else { return true; }
}
You can use FluentValidation's Must method to pass in extra data from the input object.
RuleFor(r => r.Domain)
.Must((obj, domain) => DomainExists(obj.InputDomain))
.WithErrorCode("MustExist")
.WithMessage("InputDomain must exist");
Although this will work, it is not recommended to check for database existence in the validation layer as this is verification versus validation. Instead, this kind of check should be done in the business layer.

redis servicestack client List.Remove(item) does not work

I'm developing a "Task Control System" that will allow its users to enter task description information including when to execute the task and what environment (OS, browser, etc.) the task requires.
The 'controller' saves the description information and schedules the task. When the scheduled time arrives, the scheduler retrieves the task information and 'queues' the task for a remote machine that matches the required environment.
My first cut at this used a relational database to persist the task descriptions and enough history information to track problems (about 2 weeks worth). But this is not a 'big data' problem and the relationships are simple and I need better performance.
So I'm looking for something that offers more performance.
I'm trying to use redis for this, but I'm having some problems. I'm using ServiceStack.Redis version 3.9.71.0 for the client and Redis 2.8.4 is the server.
This sample code is taken from Dan Swain's tutorial. It's updated to work with ServiceStack.Redis client v 3.9.71.0. Much of it works, but 'currentShippers.Remove(lameShipper);' does NOT work.
Can anyone see why that might be?
Thanks
public void ShippersUseCase()
{
using (var redisClient = new RedisClient("localhost"))
{
//Create a 'strongly-typed' API that makes all Redis Value operations to apply against Shippers
var redis = redisClient.As<Shipper>();
//Redis lists implement IList<T> while Redis sets implement ICollection<T>
var currentShippers = redis.Lists["urn:shippers:current"];
var prospectiveShippers = redis.Lists["urn:shippers:prospective"];
currentShippers.Add(
new Shipper
{
Id = redis.GetNextSequence(),
CompanyName = "Trains R Us",
DateCreated = DateTime.UtcNow,
ShipperType = ShipperType.Trains,
UniqueRef = Guid.NewGuid()
});
currentShippers.Add(
new Shipper
{
Id = redis.GetNextSequence(),
CompanyName = "Planes R Us",
DateCreated = DateTime.UtcNow,
ShipperType = ShipperType.Planes,
UniqueRef = Guid.NewGuid()
});
var lameShipper = new Shipper
{
Id = redis.GetNextSequence(),
CompanyName = "We do everything!",
DateCreated = DateTime.UtcNow,
ShipperType = ShipperType.All,
UniqueRef = Guid.NewGuid()
};
currentShippers.Add(lameShipper);
Dump("ADDED 3 SHIPPERS:", currentShippers);
currentShippers.Remove(lameShipper);
.
.
.
}
}
Fixed the problem by adding these overrides to the 'Shipper' class:
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
var input = obj as Shipper;
return input != null && Equals(input);
}
public bool Equals(Shipper other)
{
return other != null && (Id.Equals(other.Id));
}
public override int GetHashCode()
{
return (int)Id;
}
This working example shows how to implement List<>.Contains, List<>.Find, and List<>.Remove. Once applied to the 'Shipper' class the problem was solved!

Does asp.net MVC have Application variables?

I am busy converting a web application to MVC and have some information saved to Application variables used across multiple tenants/accounts to make things a bit more efficient.
I realise the point of MVC is to keep things as stateless as possible, Sesion State obviously makes sense to have and exists in MVC but we dont want to just convert Application to Session variables as we would rather have something more global and more secure. Do MVC applications have Application Variables? I have seen some examples where caching is used? Is this now standard and How robust/secure is this compared to Application/Session State?
Yes, you can access Application variables from .NET MVC. Here's how:
System.Web.HttpContext.Current.Application.Lock();
System.Web.HttpContext.Current.Application["Name"] = "Value";
System.Web.HttpContext.Current.Application.UnLock();
Session state or the Cache are better choices. They are mockable in MVC and are designed to store session and application-scoped data.
Static classes seems like a popular choice here. However static classes create dependencies between your types and make versioning/testing harder. Its also a bit of an odd pattern to use in a framework that is designed to break apart these kinds of dependencies. For instance, the standard ASP.NET framework is riddled with statics and sealed types. These are all replaced with mock-able instances.
"Secure" is a bit unclear in this context. Exactly what do you mean by "secure?"
I implemented something like below as an Extension for Global state variable. I put things like Site title,Service Endpoints, authorized roles
public static class ApplicationStateExtension
{
public static T GetSetApplicationState<T>(this HttpApplicationState appState, string objectName, object objectValue = null, int syncCheckMinutes = 0)
{
T retVal = default(T);
appState.Lock();
if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
{
appState[objectName + "LastSync"] = DateTime.Now;
if (objectValue != null)
appState[objectName] = objectValue;
}
if (appState[objectName] != null)
retVal = (T)appState[objectName];
appState.UnLock();
return retVal;
}
public static object GetSetApplicationState(this HttpApplicationState appState, string objectName, object objectValue = null, int syncCheckMinutes = 0)
{
object retVal = null;
appState.Lock();
if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
{
appState[objectName + "LastSync"] = DateTime.Now;
if (objectValue != null)
appState[objectName] = objectValue;
}
if (appState[objectName] != null)
retVal = appState[objectName];
appState.UnLock();
return retVal;
}
public static void SetApplicationState(this HttpApplicationState appState, string objectName, object objectValue, int syncCheckMinutes = 0)
{
appState.Lock();
if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
{
appState[objectName + "LastSync"] = DateTime.Now;
appState[objectName] = objectValue;
}
appState.UnLock();
}
public static object GetApplicationState(this HttpApplicationState appState, string objectName)
{
object retVal = null;
appState.Lock();
if (appState[objectName] != null)
retVal = appState[objectName];
appState.UnLock();
return retVal;
}
public static T GetApplicationState<T>(this HttpApplicationState appState, string objectName)
{
T retVal = default(T);
appState.Lock();
if (appState[objectName] != null)
retVal = (T)appState[objectName];
appState.UnLock();
return retVal;
}
}
So I can set them from Global.asax.cs something like this
Application.SetApplicationState("UISiteTitle",paramHelper.GetUIConfigXML<XMLParams.UISiteOptions>("UISiteOptions")
.SiteOptionCollection.Where(v => v.name.Equals("title", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault().value););
or
var uiPermissions = Application.GetSetApplicationState<XMLParams.UIPermissions>("UIPermissions", paramHelper.GetUIConfigXML<XMLParams.UIPermissions>("UIPermissions"), 30);
You can declare Application variables in Application_Start like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
var e = "Hello";
Application["value"] = e;
}
To access this on controller write:
string appVar = HttpContext.Application["value"] as string;
Make a static class?
Do they have Application Variables? Yes, MVC is a framework that sits on top of the normal asp.net framework.
I would however create a static class that uses a cache store as it's backing.

How to relate objects from multiple contexts using the Entity Framework

I am very new to the entity framework, so please bear with me...
How can I relate two objects from different contexts together?
The example below throws the following exception:
System.InvalidOperationException: The
relationship between the two objects
cannot be defined because they are
attached to different ObjectContext
objects.
void MyFunction()
{
using (TCPSEntities model = new TCPSEntities())
{
EmployeeRoles er = model.EmployeeRoles.First(p=>p.EmployeeId == 123);
er.Roles = GetDefaultRole();
model.SaveChanges();
}
}
private static Roles GetDefaultRole()
{
Roles r = null;
using (TCPSEntities model = new TCPSEntities())
{
r = model.Roles.First(p => p.RoleId == 1);
}
return r;
}
Using one context is not an option because we are using the EF in an ASP.NET application.
You will have to use the same context (you can pass the context to the getdefaultrole method) or rethink the relationships and extend the entity.
EDIT: Wanted to add this was for the example provided, using asp.net will require you to fully think out your context and relationship designs.
You could simply pass the context.. IE:
void MyFunction()
{
using (TCPSEntities model = new TCPSEntities())
{
EmployeeRoles er = model.EmployeeRoles.First(p=>p.EmployeeId == 123);
er.Roles = GetDefaultRole(model);
model.SaveChanges();
}
}
private static Roles GetDefaultRole(TCPSEntities model)
{
Roles r = null;
r = model.Roles.First(p => p.RoleId == 1);
return r;
}
Another approach that you could use here is to detach objects from one context, and then attach them to another context. That's a bit of a hack, and it may not work in your situation, but it might be an option.
public void GuestUserTest()
{
SlideLincEntities ctx1 = new SlideLincEntities();
GuestUser user = GuestUser.CreateGuestUser();
user.UserName = "Something";
ctx1.AddToUser(user);
ctx1.SaveChanges();
SlideLincEntities ctx2 = new SlideLincEntities();
ctx1.Detach(user);
user.UserName = "Something Else";
ctx2.Attach(user);
ctx2.SaveChanges();
}
Yep - working across 2 or more contexts is not supported in V1 of Entity Framework.
Just in case you haven't already found it, there is a good faq on EF at http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx
From what I understand, you want to instantiate your model (via the "new XXXXEntities()" bit) as rarely as possible. According to MS (http://msdn.microsoft.com/en-us/library/cc853327.aspx), that's a pretty substantial performance hit. So wrapping it in a using() structure isn't a good idea. What I've done in my projects is to access it through a static method that always provides the same instance of the context:
private static PledgeManagerEntities pledgesEntities;
public static PledgeManagerEntities PledgeManagerEntities
{
get
{
if (pledgesEntities == null)
{
pledgesEntities = new PledgeManagerEntities();
}
return pledgesEntities;
}
set { pledgesEntities = value; }
}
And then I retrieve it like so:
private PledgeManagerEntities entities = Data.PledgeManagerEntities;

Categories

Resources