why would Collection.IMongo.Save() not return? - c#

I am using MongoDB and I am attempting to save and it just does not return??
this is my controller:
public ActionResult doSomething(FormCollection collection)
{
if (collection == null || collection.Count == 0)
return View(Tenant);
var acct = new Account();
var whitelist = new String[]{"Name"};
TryUpdateModel(acct, whitelist, collection.ToValueProvider());
Tenant.Name = acct.Name;
Tenant.Save();
return View(Tenant);
}
and this is the Save method:
public override void Save(){
var acct = Application.Session.GetCollection<Account>();
acct.Save(this);
}
when it hits the line acct.Save(), it never returns. Any clue why this might happen?

Unless you are using safe mode, this does not return (well, returns a null), see:
http://api.mongodb.org/csharp/1.4/html/2cdf9e5b-d850-994f-c6ba-54ded02c7589.htm
This is generally how MongoDB works, i.e. using a "fire and forget" methodology for writes/updates by default. If you want to have your application block or wait around for a result then the safe mode or write concern methods are there so you can do so.

The problem was that I was trying to use DateTime to store data as a MongoObject but
MongoDB only has the following data types:
Integer (32-bit signed value)
Long (64-bit signed value)
Double (64-bit IEEE754 fp value)
String
http://code.google.com/p/morphia/wiki/PropertyAnnotation

Related

C# Nullable Static Analysis—Can you use conditional post-conditions with multiple return values?

Using C# 8+ with nullable context enabled, I have a method which returns
An enum representing various error codes, or success;
An object (if success) or null (if error)
as a ValueTuple. Aside from the null-forgiving operator, is there a way I can tell the compiler that the object is not null if the enum value indicates success?
private (EnumResult, SomeClass?) DoThing(...)
{
if (...)
return (EnumResult.Error1, null);
if (...)
return (EnumResult.Error2, null);
return (EnumResult.Success, new SomeClass(...));
}
(EnumResult result, SomeClass? someClass) = DoThing(...);
if (result == EnumResult.Success)
{
// `someClass` should not be null here, but the compiler doesn't know that.
}
I am aware there are nullable static analysis attributes which can be applied when using a bool return and an out parameter:
private bool TryDoThing(..., [NotNullWhen(true)] out SomeClass? someClass)
{
if (...)
{
someClass = null;
return false;
}
someClass = new SomeClass(...);
return true;
}
if (TryDoThing(..., out SomeClass someClass))
{
// The compiler knows that `someClass` is not null here.
}
But I couldn't determine how to apply something similar when returning a ValueTuple.
I am using an enum rather than a bool or throwing exceptions because the result code is communicated across a named pipe, where the process on the other side parses it back into an enum and then reacts according to the specific error. I am using a ValueTuple rather than an out parameter out of personal preference.
No. At this time, the MaybeNullWhen/NotNullWhen attributes only work to signal that the null state of an out parameter depends on a bool return value.
There is currently no plan to allow the null state of a variable to depend on the value of an enum return value, for example.
There is also no plan to allow an interdependence between the elements of a tuple return value, i.e. the (object? result, bool ok) Method() pattern. If you are interested in such functionality getting added to the language, feel free to start a discussion on how it would work at https://github.com/dotnet/csharplang/discussions.

C# Use returned value from Method in IF/ELSE Statement

Right now I am working on a simple program, and this is a problem I've been thinking over many times. Many times I run my methods twice because of checking on the return value before running them, and I would like to know if there is a way I can prevent this, like using the returned value from the method I am checking against. It's quite hard to explain so here is a real life example from my program.
public class SFDBRepository
{
public static Domain.SF.SFObject GetSFOrder(string WorkOrd)
{
//As you can see here i'm checking on the output of this method, before trying to return it.
if (Domain.SF.SF.GetOrder(WorkOrd) != null)
{
//If the value is not null (My method returns null if no result), return the object
return Domain.SF.SF.GetOrder(WorkOrd);
}
//Same thing happens here. My method runs twice every time almost.
else if(Domain.Building_DeliveryPerformance.Building_DeliveryPerformance.GetObject(WorkOrd) != null)
{
return Domain.Building_DeliveryPerformance.Building_DeliveryPerformance.GetObject(WorkOrd);
}
else
{
return null;
}
}
}
You can simplify this down to the following code, which will only call those methods once and make the code much more readable:
public class ShopFloorDBRepository
{
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string workOrd)
{
return Domain.ShopFloor.Shopfloor.GetOrder(workOrd) ??
Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(workOrd);
}
}
To explain why this works - the ?? operator (the null-coalescing operator!) basically says "if the returned value on the left hand side of the ?? is null, then return the value of the expression on the right hand side".
This way you only need to call your functions once.
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
//As you can see here i'm checking on the output of this method, before trying to return it.
Domain.ShopFloor.ShopFloorObject wo = Domain.ShopFloor.Shopfloor.GetOrder(WorkOrd);
if (wo != null)
{
//If the value is not null (My method returns null if no result), return the object
return wo;
}
//Same thing happens here. My method runs twice every time almost.
Domain.ShopFloor.ShopFloorObject yowo = Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(WorkOrd);
if(yowo != null)
{
return yowo;
}
/* default return */
return null;
}
PS
You're kinda doing the "Factory Pattern"
See
http://www.dofactory.com/net/factory-method-design-pattern
Looks to me like you could be using a temporary variable to hold the result, which you can test and return.
public class ShopFloorDBRepository
{
public static Domain.ShopFloor.ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
var result = Domain.ShopFloor.GetOrder(WorkOrd);
if (result != null) return result;
...
This is a common paradigm, especially when the method being called is expensive and/or has side effects you don't wish to incur twice.
Here, the "var" declaration sets the type of "result" to the type returned by the method being called; you could also use the name of the actual type.
If you wish to make two different kinds of tests like this, you'll need two different variables unless they have the same type (which in this case it appears they do).
An alternate mechanism that does require the full type, that you'll also see:
public static ShopFloorObject GetShopFloorOrder(string WorkOrd)
{
ShopFloorObject result;
if ( (result = Domain.ShopFloor.GetOrder(WorkOrd)) != null )
return result;
if ( (result = Domain.DG9_DeliveryPerformance.DG9_DeliveryPerformance.GetObject(WorkOrd)) != null)
return result;
return null;
Here you're explicitly declaring the type of the return value, then making the two calls you've indicated, testing the results against null, and returning the first non-null value.

Caching results using Massive micro-ORM

I'm using the Massive micro-ORM with a new project. I added some caching, and it all appeared to work - until I realize that the cached objects (dynamic) are still querying the database. This kills the whole point of caching.
What would be the easiest way to disconnect the result set from the database. Nearly all calls are read-only.
I'm using code like this to query records:
public static dynamic GetActive()
{
return Caching.LoadFromCache("Units_GetActive", 120,
() =>
{
dynamic tbl = new Units();
return tbl.Find(Enabled: 1, orderby: "SortOrder");
});
}
My caching code looks like this:
public static dynamic LoadFromCache(string cacheKey, int secondsToCache, Func<object> query)
{
object tocache = null;
// result will always get the value here
// tocache will only have the value when it was pulled from our method
object result = MemoryCache.Default[cacheKey] ?? (tocache = query.Invoke());
if (secondsToCache > 0)
{
if (tocache != null) // only save to cache if it wasn't there
MemoryCache.Default.Add(cacheKey, tocache, DateTime.UtcNow.AddSeconds(secondsToCache));
}
else
{
// remove from cache only if secondsToCache was zero or less
MemoryCache.Default.Remove(cacheKey);
}
return result;
}
The caching code works. The problem is the dynamic object returned (IEnumerable<dynamic>) opens another connection to the database.
Ideas?
Tim Medora had the right idea.
I changed my caching code to this:
public static dynamic LoadFromCache(string cacheKey, int secondsToCache, Func<object> query)
{
object tocache = null;
// result will always get the value here
// tocache will only have the value when it was pulled from our method
object result = MemoryCache.Default[cacheKey] ?? (tocache = query.Invoke());
if (secondsToCache > 0)
{
// If this came from Massive, we need to get the list instead of opening a
// database connection each time we enumerate. I check the type, because other things
// are stored.
if (tocache is IEnumerable<dynamic>)
{
tocache = ((IEnumerable<dynamic>)tocache).ToList<dynamic>();
result = tocache;
}
if (tocache != null) // only save to cache if it wasn't there
MemoryCache.Default.Add(cacheKey, tocache, DateTime.UtcNow.AddSeconds(secondsToCache));
}
else
{
// remove from cache only if secondsToCache was zero or less
MemoryCache.Default.Remove(cacheKey);
}
return result;
}
The ToList<dynamic>() was the key part. It seems to work as expected now. ToList<T> is an extension method in the System.Linq namespace.

Data Caching chances of returning null value from function

I have a function written in C# which return collection of business-entity (make) after checking and inserting in cache.
public static Collection<CProductMakesProps> GetCachedSmartPhoneMake(HttpContext context)
{
var allMake = context.Cache["SmartPhoneMake"] as Collection<CProductMakesProps>;
if (allMake == null)
{
context.Cache.Insert("SmartPhoneMake", new CModelRestrictionLogic().GetTopMakes(), null,
DateTime.Now.AddHours(Int32.Parse(ConfigurationManager.AppSettings["MakeCacheTime"])),
Cache.NoSlidingExpiration);
allMake = context.Cache["SmartPhoneMake"] as Collection<CProductMakesProps>;
}
return allMake;
}
I am using it in some other page as follows
var lobjprodMakeCol = CBrandCache.GetCachedSmartPhoneMake(Context);
//CBrandCache is the class which contain the method
Is it possible that I get null value in the lobjprodMakeCol
Thanks.
Edit
Note new CModelRestrictionLogic().GetTopMakes() is a function which fetches the records from database.
It will return a collection weather of count 0 or more.
There are few of possibilities when your function could return null - they are
GetTopMakes function it self returns null
The cache expiration time is zero (MakeCacheTime config entry has zero value)
The cast as Collection<CProductMakesProps> fails - possible if GetTopMakes
return some different type.
I would prefer below version which would not return null in all of above cases
var allMake = context.Cache["SmartPhoneMake"] as Collection<CProductMakesProps>;
if (allMake == null)
{
allMake = new CModelRestrictionLogic().GetTopMakes();
context.Cache.Insert("SmartPhoneMake", allMake,
null, DateTime.UtcNow.AddHours(Int32.Parse(
ConfigurationManager.AppSettings["MakeCacheTime"])), Cache.NoSlidingExpiration);
}
return allMake;
Also note that use of DateTime.UtcNow that would avoid any surprises such as day-light savings etc.
Yes it is possible, if the cast as Collection<CProductMakesProps> fails then a null will be assigned to allMake, so this depends heavily on what you are returning from new CModelRestrictionLogic().GetTopMakes().
Based on the assumption that most cache and/or dictionary collections will allow you to check for the presense of a specific key, I would suggest a slightly more streamlined way of writing this:
public static Collection<CProductMakesProps> GetCachedSmartPhoneMake(HttpContext context)
{
if (!context.Cache.ContainsKey("SmartPhoneMake") || context.Cache["SmartPhoneMake"] == null)
{
context.Cache.Insert("SmartPhoneMake"
, new CModelRestrictionLogic().GetTopMakes()
, null
, DateTime.Now.AddHours(Int32.Parse(ConfigurationManager.AppSettings["MakeCacheTime"]))
, Cache.NoSlidingExpiration);
}
return context.Cache["SmartPhoneMake"] as Collection<CProductMakesProps>;
}

Explicit Int Conversion Overflow

Problem
When I pass the value to an int variable where the value exceed the maximum value for int, the value of the int variable become 0.
Background
I use the following steps to retrieve my data. I do not use any try-catch block without throwing an exception.
Step 1
In my WCF Service, I retrieve a DataTable using IBM.Data.DB2.iSeries.iDB2DataAdapter.Fill(DataSet)
Step 2
Then I convert the DataTable to List<T> using the code :
public static List<T> DataTableToList<T>(DataTable dt)
{
List<T> tableEntity = new List<T>();
foreach (DataRow row in dt.Rows)
{
T rowEntity = Activator.CreateInstance<T>();
rowEntity.GetType().GetProperties().Where(o => dt.Columns.OfType<DataColumn>()
.Select(p => p.ColumnName).Contains(o.Name)).ToList()
.ForEach(o => o.SetValue(rowEntity, row[o.Name], null));
tableEntity.Add(rowEntity);
}
return tableEntity;
}
with the type :
public class Client
{
public int ID { get; set; }
public string Name { get; set; }
}
Step 3
I return it using the WCF service method :
[OperationContract]
public string GetClients()
{
List<Client> clients = new DB().RetrieveClients();
return Tools.SerializeObjectToXML<List<Client>>(clients);
}
with the helper method for serializing :
public static string SerializeObjectToXML<T>(T item)
{
XmlSerializer xs = new XmlSerializer(typeof(T));
using (StringWriter writer = new StringWriter())
{
xs.Serialize(writer, item);
return writer.ToString();
}
}
Step 4
Then in the Client Application, I retrieve it from the Service Reference with the default binding of WSHttpBinding with the code :
List<Client> clients = Tools.DeserializeXMLToObject<List<Client>>(new SomeServiceClient().GetClients());
with the helper method for deserializing :
public static T DeserializeXMLToObject<T>(string xmlText)
{
if (string.IsNullOrEmpty(xmlText)) return default(T);
XmlSerializer xs = new XmlSerializer(typeof(T));
using (MemoryStream memoryStream = new MemoryStream(new UnicodeEncoding().GetBytes(xmlText)))
using (XmlTextReader xsText = new XmlTextReader(memoryStream))
{
xsText.Normalization = true;
return (T)xs.Deserialize(xsText);
}
}
Question
The msdn says that :
When you convert from a double or float value to an integral type, the value is truncated. If the resulting integral value is outside the range of the destination value, the result depends on the overflow checking context. In a checked context, an OverflowException is thrown, while in an unchecked context, the result is an unspecified value of the destination type.
Why do the value of Client.ID becomes 0 when the value from the database exceeds the maximum allowed for int?
Is it because it is an unchecked context? If it is, how would I know?
My code is in C#, framework 4, build in VS2010 Pro.
Please help, thanks in advance.
There is something fishy going on here. SetValue doesn't do cast/conversions (not even from uint to int, just tested). You would be much better enlarging the ForEach code in a real foreach and debugging it.
For example:
foreach (var o in rowEntity.GetType().GetProperties().Where(o => dt.Columns.OfType<DataColumn>()
.Select(p => p.ColumnName).Contains(o.Name)))
{
if (o.Name == "ID")
{
// Put a breakpoint here
}
o.SetValue(rowEntity, row[o.Name], null));
}
By default, arithmetic overflow compiler switch is turned off in Visual Studio. To enable it:
Right-click on the project and click Properties.
Click on the Build tab.
Click on the Advanced… button.
Check the Check for arithmetic overflow/underflow checkbox.
I do not know exactly where you can find if you are checked or unchecked. But it depends on your compilers options as stated in http://msdn.microsoft.com/en-us/library/khy08726(v=vs.100).aspx
And as Thorsten Dittmar said, you can better use the DataContract to easily send the clients.
And if it overflows you can better use a long for the id instead of an int. That way it has way more positions (long == Int64). And if all of your Id's are > 0 you can use a unsigned int or unsigned long as your Id. Unsigned means that instead of also having numbers lower then zero it is only positive and therefor twice the positive positions.
Int32
Uint32
Int64 (long)
Uint64 (ulong)
Just a question: Why do you transmit the list as a string instead of doing the following:
[OperationContract]
public Client[] GetClients()
{
List<Client> clients = new DB().RetrieveClients();
return clients.ToArray();
}
and declare the Client class like:
[DataContract]
public class Client
{
[DataMember]
public int ID;
[DataMember]
public string Name;
}
Also: If the type of ID in the database allows for values larger than Int32.MaxValue, why would you use an Int32 at all and not an Int64?
As for overflow checking: I know that using Convert.ToInt32(Int64.MaxValue); throws an exception while int i = (int)Int64.MaxValue does not.

Categories