I had applied the following code :
var country = from cnty in this.GetAll<CompanyDefinition>().ToList()
where cnty.IsImported = true
select new {
CompanyDefinitionID = cnty.CompanyDefinitionID
, CompanyDefinitionName = cnty.Company.CompanyName + "(" + cnty.Country.CountryCode + "," + cnty.NaicsCode.NaicsCode1 + ")"
};
And I am getting Object Reference error. Its pointing to "select new". Whats the correct way?
The problem is Company, Country or NaicsCode is null, you would need to check this before attempting to access their properties. For example, you could re-write your query as:
var country = from cnty in this.GetAll<CompanyDefinition>()
where cnty.IsImported && cnty.Company != null && cnty.Country != null && cnty.NaicsCode != null
select new {
...
}
If you are employing lazy loading, then using ToList() method is not proper. After calling ToList(), IQueryable<> object is materialized to IEnumerable<>; thus database is not queried for Company or Country references. Try removing ToList() function.
Related
I am currently developing a MS Dynamics CRM 2013 - Plugin.
When I try to assign a string-value to a key of a field of an entity it gives me the 'keynotfound'-exception.
This leaves me clueless, because I can verify the key is existing. The key I give is also written correctly, and the data types are compatible, too.
Here's some extra info:
I tried resolving the issue with a server reboot. Nothing.
Remote Debugging is not an option.
I swapped "retrieved.EntityCollection.Entities[i][forField]" with retrieved.EntityCollection.Entities[i]["new_name"] and everything was working fine (kind of pointing out the obvious here, but "new_name" is not the key I try to access).
The execution stops # "if (retrieved.EntityCollection.Entities[i][forField].ToString() != "" && !overwriteExisting)"
Have you got an idea to help me out?
public void GenerateNumberForEntityCollection(string target)
{
try
{
// variables for number generation
bool overwriteExisting = (bool)preImageEntity["new_overwriteexisting"];
int suffixstart = (int)preImageEntity["new_suffixstart"];
string forField= preImageEntity["new_forfield"].ToString();
string prefix = preImageEntity["new_prefix"].ToString();
string postfix = preImageEntity["new_postfix"].ToString();
string separator = preImageEntity["new_separator"].ToString();
// Build query to get all the entries
RetrieveMultipleResponse retrieved;
int PageNumber = 1;
string PagingCookie = string.Empty;
int PageSize = 5000;
string[] Columns = { forField };
QueryExpression query = new QueryExpression()
{
EntityName = target,
ColumnSet = new ColumnSet(Columns),
PageInfo = new PagingInfo()
{
PageNumber = 1,
Count = PageSize
}
};
do
{
if (PageNumber != 1)
{
query.PageInfo.PageNumber = PageNumber;
query.PageInfo.PagingCookie = PagingCookie;
}
RetrieveMultipleRequest retrieve = new RetrieveMultipleRequest();
retrieve.Query = query;
retrieved = (RetrieveMultipleResponse)service.Execute(retrieve);
// Now that all entities are retrieved, iterate through them to gen. the numbers
int i = 0;
foreach (Entity entity in retrieved.EntityCollection.Entities)
{
if (retrieved.EntityCollection.Entities[i][forField].ToString() != "" && !overwriteExisting)
{
//continue;
}
else
{
retrieved.EntityCollection.Entities[i][forField] = prefix + separator + suffixstart.ToString() + separator + postfix;
}
suffixstart++;
service.Update(retrieved.EntityCollection.Entities[i]);
i++;
}
if (retrieved.EntityCollection.MoreRecords)
{
PageNumber++;
PagingCookie = retrieved.EntityCollection.PagingCookie;
}
} while (retrieved.EntityCollection.MoreRecords);
}
catch (Exception e)
{
tracing.Trace("GenerateNumberForEntityCollection: Failed: {0}", e.ToString());
}
}
How did you verify that the key exists?
If the data in a field is null, the Entity instance will not contain that key, even if you specify it in the query's ColumnSet.
This will return you a boolean, indicating if the key exists in the Entity. You can do this control before attempting to read the attribute.
var attributeExists = retrieved.EntityCollection.Entities[i].Contains(forField)
The control below you've done will result in the exception you're getting if the field is null. Just make sure that the attribute exists before.
retrieved.EntityCollection.Entities[i][forField].ToString() != ""
Additionally, you'll get a null reference exception if no records were returned from the query. Make you do a null check on retrieved.EntityCollection.Entities.
When you are querying data in Dynamics CRM it is important to know that record fields having null values in the database are not included in the Attributes collection of the Entity instances being returned.
Getting a value from an Entity's Attribute with this construct:
var value = retrieved.EntityCollection.Entities[i][forField].ToString();
succeeds when attribute forField already has a value in the database, but fails when its current value is null.
Therefore the preferred method to get the attribute values from an entity is GetAttributeValue<T>, like this:
var value = retrieved.EntityCollection.Entities[i].getAttributeValue<string>(forField);
This method returns the value when the attribute exists in the attribute collection, otherwise it returns null.
If any of the fields among
(new_forfield,new_prefix,new_postfix,new_separator) has null value,
that column does not present in the retrieved object and you are trying to get the value of null column preImageEntity["new_forfield"] which will throw keynotfound'-exception ,
so change the code
string forField= preImageEntity["new_forfield"].ToString();
string prefix = preImageEntity["new_prefix"].ToString();
string postfix = preImageEntity["new_postfix"].ToString();
string separator = preImageEntity["new_separator"].ToString();
to
string forField = preImageEntity.Attributes.Contains("new_forfield")? preImageEntity["new_forfield"].ToString():"";
string prefix = preImageEntity.Attributes.Contains("new_forfield") ? preImageEntity["new_prefix"].ToString() : "";
string postfix = preImageEntity.Attributes.Contains("new_forfield") ? preImageEntity["new_postfix"].ToString() : "";
string separator = preImageEntity.Attributes.Contains("new_forfield") ? preImageEntity["new_separator"].ToString() : "";
this will check for field, if it exists than will parse the value to
string else will assign empty string.
I'm trying to optimize the following method by having it return only the data my program actually needs for its calculations. In the past the dataset hasn't been that large so I haven't needed to optimize this too much. More recently, my dataset grew from about 30k records to 700k records, so I'm trying to optimize this further.
public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<int> hashKey)
{
log.Info("Reading in raw thresholds from db");
using (FAI db= new FAI ())
{
rawThresholds = (from thr in db.Thresholds
where thr.CalculatedDate == maxDateTimeVal
where thr.ErrorSourceId == inputtedESourceID
where hashKey.Contains(thr.HashKey)
select thr).ToList();
}
log.Info("Read in " + rawThresholds.Count() + " threshold records for error source id: " + inputtedESourceID + ".");
}
I got the method to return about 200k rows from 700k by adding the hashKey.Contains(thr.HashKey), but I want to take this one step further by doing the contains on a combination of 2 fields instead of just 1. The catch is that this has to happen on the DB for it to improve my runtimes. There is already post processing that only acts on the rows the program will need.
I want to be able to give the method the following as an input and have the contains (or something similar) act on the new HashKeyHostId object:
public HashKeyHostId{public int hashKey; public int hostId;}
public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<HashKeyHostId> hashKeyHostIdPairs){
}
There's probably a very simple way of doing this that I'm not thinking of.
Edit:
In response to James's comment - I don't believe this would work. The hashkey variable would now be an object containing pairs of integers instead of just 1 integer. This alone would prevent you from doing a .contains because it's no longer a primitive. It'd be the "public HashKeyHostId{public int hashKey; public int hostId;}" object I posted above. The new requirement is that a hashkey/hostId combo have to match up to 1 record in the DB.
If you're suggesting I do what Janne said (give it a list of hash keys and a list of host ids), I'm fairly certain this would return all results where the hashkey belongs to any of the hostids in the second list (aka, any combination of the two lists). I need it to only return rows with the specified combinations, not combinations of anything in the two lists.
Edit2: Sample dataset:
Hashkeys = 100,101,102,103
HostIds = 1,2,3,4,5,6,...,10000
I'd give it a list like
List<HashKeyHostId> data = new List<HashKeyHostId>()
{new HashKeyHostId(100,1),new HashKeyHostId(101,5)}
I believe the query Janne/James are suggesting would return records for any of those combinations (100,1; 100,5; 101,1; 101,5;). I need it to only return records for 100,1 and 101,5.
edit3:
I tried doing a where hashkeyHostIdpair.Any(o=> o.hashkey==thr.HashKey && o.hostid==thr.HostId)", but that errored out with the same "Unable to create a constant value of type 'RTM_DB.HashKeyHostId'. Only primitive types are supported in this context." message. It doesnt look like you can do a .Any or a .contains on a list of non-primitive types. I even tried making my own .Any with a where clause and that threw the same exception. (where hashkeyHostIdpair.Where(o=>o.hostid==thr.HostId && o.hashkey==thr.HashKey).Count()>0))
edit4: Per Josh's suggestion I tried this:
rawThresholds=fai.Thresholds.Where(o=>o.CalculatedDate==maxDateTimeVal)
.Where(o=>o.ErrorSourceId==inputtedESourceID)
.Where(o=> hashkeyHostIdpair.Contains(new HashKeyHostId(){ hashkey=o.HashKey, hostid = o.HostId})).ToList();
but it errored out with {System.NotSupportedException: Unable to create a constant value of type 'RTM_DB.HashKeyHostId'. Only primitive types ('such as Int32, String, and Guid') are supported in this context
There's probably a very simple way of doing this that I'm not thinking of.
Yeah, there is
where hashKey.Contains(someValue) && hashKey.Contains(someOtherValue)
Something along this would maybe be what you want to do?
public void readRawThresholdsInList(int inputtedESourceID, DateTime maxDateTimeVal, List<int> hashKeys, List<int> hostIds)
{
log.Info("Reading in raw thresholds from db");
using (var db = new FAI())
{
var rths = (from thr in db.Thresholds
where thr.CalculatedDate == maxDateTimeVal
&& thr.ErrorSourceId == inputtedESourceID
select thr);
if (hashKeys != null && hashKeys.Count() > 0)
rths = rths.Where(rth => hashKeys.Contains(rth.HashKey))
if (hostIds != null && hostIds.Count() > 0)
rths = rths.Where(rth => hostIds.Contains(rth.HostId)) // FieldName?
rawThresholds = rths.ToList();
}
log.Info("Read in " + rawThresholds.Count() + " threshold records for error source id: " + inputtedESourceID + ".");
}
-- edit --
You could do something like this, but I wouldnt recommend it. Figure out a value which you can multiply the HashKey safely so HostId will always be in the last digits
var filters = new int[] { 100 * 100 + 1 , 101 * 100 + 5 }; // 10001 & 10105
var rths = (from rth in db.Thresholds
where rth.CalculatedDate == maxDateTimeVal
&& rth.ErrorSourceId == inputtedESourceID
&& filters.Contains(rth.HashKey * 100 + rth.HostId)
select rth).ToList();
If you have something like
List<HashKeyHostId> data = new List<HashKeyHostId>() {
new HashKeyHostId { hashKey = 100, hostId = 1 },
new HashKeyHostId { hashKey = 101, hostId = 5 }
}
You can use it in a contains like this:
<somequery>.Where(x => data.Contains(new HashKeyHostId { hashKey = x.HashKey, hostId = x.HostId }))
Note the use of the object initializer syntax instead of a constructor.
This should get translated to SQL with each item in the list being appended to the WHERE clause like:
WHERE ([t0].[HashKey] = #p0 AND [t0].[HostId] = #p1) OR
([t0].[HashKey] = #p2 AND [t0].[HostId] = #p3) OR ...
I'm trying to add a where clause to an existing LINQ DataBind but nothing I do works. The where clause I want to add checks if in the table refAuthSigner the column IsActive == 1.
Here's my existing Query:
// populates Authorized Signer dropdownlist
using (dbPSREntities10 myEntities = new dbPSREntities10())
{
var allSigners = from refAuthSigner in myEntities.refAuthSigners <--- where clause somewhere around here??
select new
{
refAuthSignerID = refAuthSigner.refAuthSignerID,
refAuthSignerName = refAuthSigner.refAuthSignerFirst + " " + refAuthSigner.refAuthSignerLast
};
ddlAuthSigners.DataSource = allSigners;
ddlAuthSigners.DataValueField = "refAuthSignerID";
ddlAuthSigners.DataTextField = "refAuthSignerName";
ddlAuthSigners.DataBind();
}
I want to add a where clause which is something like:
var allSigners = from refAuthSigner in myEntities.refAuthSigners
where refAuthSigner.IsActive == 1
This code isn't right and just wondering how I would incorporate the where clause into the code. Thanks!
Simply use:
where refAuthSigner.IsActive
Since it's a boolean value you cannot compare it to an integer. It is true or false, not 1 or 0. (Some langauges conflate the two, C# is not one of them.)
There is no need to compare IsActive to anything. where needs a boolean value, and IsActive is a boolean value. You already have exactly what you need.
You could make the statement:
var allsigners = refAuthSigner.Where(x => x.refAuthSigner.IsActive)
Try this:
var allSigners = from refAuthSigner in myEntities.refAuthSigners
where refAuthSigner.IsActive
select new
{
refAuthSignerID = refAuthSigner.refAuthSignerID,
refAuthSignerName = refAuthSigner.refAuthSignerFirst + " " + refAuthSigner.refAuthSignerLast
};
Operator of '==' cannot be applied to operands of type 'bool' and 'int'. IsActive is type bit in SqlServer
If this is the error you are getting try using Any instead of Where as it returns bool
// populates Authorized Signer dropdownlist
using (dbPSREntities10 myEntities = new dbPSREntities10())
{
var allSigners = from refAuthSigner in myEntities.refAuthSigners
where refAuthSigner.IsActive
select new
{
refAuthSignerID = refAuthSigner.refAuthSignerID,
refAuthSignerName = refAuthSigner.refAuthSignerFirst + " " + refAuthSigner.refAuthSignerLast
};
ddlAuthSigners.DataSource = allSigners;
ddlAuthSigners.DataValueField = "refAuthSignerID";
ddlAuthSigners.DataTextField = "refAuthSignerName";
ddlAuthSigners.DataBind();
}
I want to store null for some of the keys in HttpRuntime.Cache as I dont want to again go to Database to find that there is no entry for that key.
So first time, it goes to database and fills the cache. The intent is to serve the following calls using cached data instead of doing the database call.
Here is the code that I am using the following:
Info info = null;
if (HttpRuntime.Cache["Info_" + id.ToString() + "_" + quantity.ToString()] != null)
info = HttpRuntime.Cache["Info_" + id.ToString() + "_" + quantity.ToString()] as Info;
if (info == null)
{
info = (from dd in dc.Infos
where dd.id == id && dd.active == true && dd.quantitytooffset == quantity
select dd).SingleOrDefault();
HttpRuntime.Cache.Add("Info_" + id.ToString() + "_" + quantity.ToString(), info, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null);
}
The last line of code i.e. HttpRuntime.Cache.Add throws an System.ArgumentNullException: Value cannot be null.
Any idea if this is possible or I need to use other datastructure to store null values and look up later?
You could use your own "null" value to place into cache.
For example,
private static Info NULL_INFO = new Info();
Then you could use that instead of null in HttpRuntime.Cache.Add and later after retrieval from cache check that you didn't get your NULL_INFO
if ( info == NULL_INFO) // if you don't have equality operator overloaded, otherwise you'd better use ReferenceEquals()
// return empty data
else if (info == null)
// proceed with try to load from database
I wrote a blog post recently about how the null keyword is often abused leading to this kind of confusion. In your particular case I would look at using an option type to indicate the lack or presence of data rather than null.
I have a simple implementation of an Option type you can use here
The usage would then be something like:
if (HttpRuntime.Cache["xyz"] == null)
// Impossible to make a distinction between whether or not the cache value is missing
// or if it is present but explicitly a null value...
HttpRuntime.Cache["xyz"] = Option<String>.None();
// We have now explicitly stated that the cache contains xyz but the value is null...
HttpRuntime.Cache["xyz"] = Option<String>.Some("hello world");
if (HttpRuntime.Cache["xyz"].IsSome)
{
// cache contains a non-null value for xyz...
}
You just need to check whether the value obtained from your data source is not null before trying to add it back to the cache, see below:
Info info = null;
if (HttpRuntime.Cache["Info_" + id.ToString() + "_" + quantity.ToString()] != null)
info = HttpRuntime.Cache["Info_" + id.ToString() + "_" + quantity.ToString()] as Info;
if (info == null)
{
info = (from dd in dc.Infos
where dd.id == id && dd.active == true && dd.quantitytooffset == quantity
select dd).SingleOrDefault();
if (info != null)
{
HttpRuntime.Cache.Add("Info_" + id.ToString() + "_" + quantity.ToString(), info, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High, null);
}
}
As you are using the as Info conversion at the beginning of your code, if the key isn't present in the cache it'll return a null value anyway, so you don't need to store the null value in cache. Storing null values in the cache doesn't really serve any use, so there's a reason the framework is not allowing you to do that.
Also as a slight side-note, it would be good to create your cache key once, then re-use it rather than reconstructing it every time it's used. For instance:
var key = string.Format("Info_{0}_{1}", id, quantity);
Then just use:
HttpRuntime.Cache[key]
When accessing it, it'll make your code less prone to typo errors.
This is a generic static class/method to solve this quite common problem (null which means "i checked and it doesn't exist, I don't need to check again").
This solution wraps the value like in the other answers.
Usage example
var user = await Cached.Get(
_cache, userName,
async () => _dbContext.LoadAsync<DbUser>(userName)));
Implementation
public class CachedEntry<T>
{
public CachedEntry(T value)
{
Value = value;
}
public T Value { get; }
}
public static async Task<T> Get<T>(IMemoryCache cache,
string key, Func<Task<T>> getDelegate)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
var cachedEntry = cache.Get<CachedEntry<T>>(key);
if (cachedEntry == null)
{
var result = await getDelegate();
cachedEntry = new CachedEntry<T>(result);
cache.Set(key, cachedEntry);
}
return cachedEntry.Value;
}
For some reason, when I add the ternary if statement to this bit of code, a NullPointerException is thrown. I'm not sure quite why...any ideas? This is the method for jqGrid - returning the Json data.
var gridModel = from entity in vendorList.AsQueryable()
select new
{
VendorId = "<a href='/Admin/DetailsPlan/" + entity.VendorId + "'><img src='/Images/next_icon_sm.png' class='icon' alt='View Vendor' /></a>",
VendorNm = entity.VendorNm,
Phone = (entity.Phone.Length < 5) ? String.Format("{0:(###) ###-####}", Convert.ToInt64(entity.Phone)) : entity.Phone,
City = entity.City,
State = entity.LkState.StateAbbr
};
Can you not have a ternary if statement in that location?
var gridModel = from entity in vendorList.AsQueryable()
let unformattedPhone = entity.Phone??string.Empty
select new
{
VendorId = "<a href='/Admin/DetailsPlan/" + entity.VendorId + "'><img src='/Images/next_icon_sm.png' class='icon' alt='View Vendor' /></a>",
VendorNm = entity.VendorNm,
Phone = (unformattedPhone.Length < 5) ? String.Format("{0:(###) ###-####}", Convert.ToInt64(unformattedPhone)) : unformattedPhone,
City = entity.City,
State = entity.LkState.StateAbbr
};
This may solve your problem.
One question, is entity.Phone null? If so, that would be the cause.
Side note: I have to say, that is an odd way of storing a phone number..
UPDATE
The problem is with the "entity.Phone.Length" part. If Phone is null, then you can't access it's length property... hence the error. So you need to add a null test. Something like:
Phone = ((entity.Phone != null) && (entity.Phone.Length < 5)) ? String.Format("{0:(###) ###-####}", Convert.ToInt64(entity.Phone)) : entity.Phone
That way, if it is null you are just emitting a null value.