What is the difference between AddObject and AddToMyTable (specific table name)? - c#

I'm very newbie in MVC 4 and Entity-Framework
If this question does not make sense, please let me explain better.
During the example I'm working on, I have noticed that I can make an insertion to database either using AddObject or AddToMyTableName.(my specific table name which is exist in database)
So I'm kinda confused what is the difference between these?
And which one I should use in what cases?
Here is very simplified example:
In the controller:
This is example for AddObject:
using (myProj.Models.myProjEntities db = new Models.myProjEntities())
{
myProj.Models.TestClass myTestClass = new myProj.Models.TestClass();
myTestClass.prop1 = "test1";
myTestClass.prop2 = "test2";
db.MyTable.AddObject(myTestClass);
db.SaveChanges();
}
And here is the example for AddToSpecificTable:
using (myProj.Models.myProjEntities db = new Models.myProjEntities())
{
myProj.Models.TestClass myTestClass = new myProj.Models.TestClass();
myTestClass.prop1 = "test1";
myTestClass.prop2 = "test2";
db.AddToMyTable(myTestClass);
db.SaveChanges();
}
Both of them are inserting the values to db and both are working same in my example. I'm pretty sure there are some cases when one of them is working , the other will not.
Can anyone please explain the difference?
Thanks

The AddTo<TEntity> method is now considered deprecated and has been used with EF4 and previous versions. With EF4.x the new AddObject() was introduced as replacement method for AddTo<TEntity> but for some (unknown) reason the AddTo<TEntity> method was still available even though it's was recommended to use the new AddObject() method. As of now, with EF5+ you can just use Add(). It's hard to find the exact reasons for the replacement of the methods but I guess this is most probably historical reasons and as the EF evolved so the methods were changed to reflect the new versions.
So if you consider why (if in any scenario) the one is better than the other, than just use the most common one (Of course if you don't have some version restrictions like, if you are using EF 4 for example). Otherwise you are not gaining anything and usually after some method is marked as deprecated sooner or later it's removed, so if you use AddTo<TEntity> you might need to rewrite parts of your code due to the fact that in some future version this method is no longer presented.

Related

MongoDocument Object only gets partially populated when querying

I have a collection of users that I'm trying to read from the database, but for some reason some strange behavior takes place that I can't really figure out. Hopefully, somebody can suggest or help me find the root of this problem.
So basically, what happens is that whenever I call this code in my HomeController.cs:
var users = await _database.GetCollection<User>("ApplicationUsers").FindAsync(_ => true);
var userList = users.ToList();
it only populates userList partially, meaning only the ID and ConcurrencyStamp properties get filled, but the other properties always end up being null (as seen in: https://i.imgur.com/RTF8ljL.png)
But whenever I add this line right after the database connection initialization in the Startup.cs:
database.GetCollection<User>("ApplicationUsers");
Then suddenly userList does get populated with all the other information (as seen in https://i.imgur.com/f5IV7fh.png)
So in order for it to work, I have to get the collection right after the connection gets initialized which I'm not really fond of, because I don't have to do this for other collections. So my mongo connection code would have to look like this in the Startup.cs:
var mongoUrl = new MongoUrl(config.GetSection("DatabaseSettings:ConnectionString").Value);
var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.ClusterConfigurator = cb => ConfigureCluster(cb);
var client = new MongoClient(mongoClientSettings);
var database = client.GetDatabase(config.GetSection("DatabaseSettings:DatabaseName").Value);
database.GetCollection<User>("ApplicationUsers"); // TODO: This is needed just to let Mongo Driver know to which class to deserialize this collection
services.AddSingleton<IMongoDatabase>(database);
var pack = new ConventionPack()
{
new CamelCaseElementNameConvention(),
new IgnoreExtraElementsConvention(true),
new DictionaryRepresentationConvention(DictionaryRepresentation.ArrayOfArrays)
};
ConventionRegistry.Register("DatabaseConventions", pack, t => true);
I'm guessing something happens between the execution of Startup.cs and HomeController.cs that causes the deserialization to mess up?
Update:
The same behavior seems to happen on a clean project, the only nuget packages I installed are the official mongodb driver and AspNetCore.Identity.Mongo by Matteo Fabbri. This strange deserialize behavior does not happen when I use getCollection for other classes. The problem lies with ApplicationUser which extends from MongoUser (a class made available by the AspNetCore.Identity.Mongo library)
Update 2:
Turns out that MongoUser class from the AspNetCore.Identity.Mongo library is allergic to the ConventionPack that was registered. I tested this by getting the collection before and after the registration of the database conventions. Now finding a proper solution for this.
Update 3:
Also I found out that documents are saved with properties named in Upper Camel Case, which could be the cause for mongodb driver's confusion. It seems that the conventions set to save them in CamelCase is being ignored for this particular class (ApplicationUser).
I managed to solve the problem. The issue was the order of code execution. The convention pack was registered after MongoIdentity and the database was initialized. During the initialization of MongoIdentity and the Database, the ApplicationUser was configured to not have the CamelCaseElementNameConvention in the pack, which led to the class being saved in UpperCamelCase and therefore cause confusion when retrieving the collection when the registered ConventionPack was active.
For whoever struggles with strange behavior where you may think your code should work, remember that the order of code execution is very important and could very well be the cause of the behavior. Good luck to y'all!

Fill object from SQL result

I have a regular C# class called "vehicle" with properties like Name, NumberPlate, MaxSpeed, etc.
All the data for the class is stored in a SQLite Database where I have a Table "Car" and "Boat". The tables colums have the same names as the class properties (however, there are more columns than class properties - vehicle is a more generic abstraction). At the moment, I have to assign the result of the query individually one by one like this:
while (await statement.StepAsync())
{
myVehicle.Name = statement.Columns["Name"];
//[...]
myVehicle.MaxSpeed = decimal.TryParse(statement.Columns["MaxSpeed"]);
}
Additionally, I have to check if some columns exist ("Car" and "Boat" have a different set of columns) which is more code than I'd like it to be.
I read about EntityFramework to map my db table to my class - but that seems overkill. My requirement is to map properties and columns that have the same name and ignore everything else.
Is there a "easy" (dev time, lines of code) way to map my table columns to my class?
Thanks for reading!
The restrictions in phone 8 mean that a lot of the standard answers to this ("just use {some ORM / micro-ORM}") won't apply, since they don't work on phone 8. You can probably use reflection for a lot of this, but: reflection can be (relatively) slow, so it depends on how much data you will be processing. If it is occasional and light: fine, reflect away.
Runtime meta-programming (the tricks used by libraries like "dapper" in full .NET to make these things really fast) is not available on restricted runtimes, so if you want to avoid lots of boiler-plate that leaves build-time meta-programming. At the simplest, I wonder if you could use something like T4 to automate creating these methods for you as C#. There are also ways to use the reflection-emit API to construct assemblies (at build-time) for phone 8, but that is a pretty hard-core route.
My thoughts:
if the amount of types here isn't huge, just write the code
if you have a lot of types, or you just feel like it, consider a build-time code-generation meta-programming step; you might even think "hmm, is this something I could make available to the community?"
of course, the first thing to do is to check that such a thing doesn't already exist
There is a little helper which might fit your case. Basically, it will take a dictionary and try it's best to populate a objects properties using reflection. I didn't try it by myself though.
You'd simply do something like:
while (await statement.StepAsync())
{
myVehicle = DictionaryToObject<Car>(statement.Columns);
}
It might need some further work to get it running but maybe a good start.

Replacement for big switch?

I have a page named "ReportController.aspx" whose purpose is to instantiate a report (class) based on query string parameters
switch (Request.QueryString["Report"])
{
case "ReportA":
CreateReportAReport("ReportA's Title");
break;
case "ReportB":
CreateReportBReport("ReportB's Title");
break;
case "ReportC":
CreateReportCReport("ReportC's Title");
break;
case "ReportD":
CreateReportDReport("ReportD's Title");
break;
...
Basically, each time a new report is needed there will be this overhead of adding a case and adding a method. This switch statement could get very very long. I read that is is possible to use a Dictionary to map a Report to ?. How would this look using a Dictionary (assuming this is a better way).
Also, CreateReportXReport method basically passes a bunch of additional QueryString values to the report class's constructor (each report class has a different constructor).
There's no getting around having to type in the new information somewhere; the key is to get it out of the code, to avoid recompiling and redeploying for such a trivial change.
Some good options are to list these value in an XML config file, or better yet, your database.
You'll probably want to fill out a dictionary with this data, whatever the source. This will:
Make it easy to cache
Make for clean, fast code
When the time comes to pull your data out of configuration into code, you'd add items to the dictionary like so:
Dictionary<string, IReportCreator> = configDataGetter.GetReportDataFromDB().
ToDictionary(r => r.Name, myReportCreatorFactory(r => r.ReportID))
This example assumes your getting data as entity object of some kind, and using a factory that would use a strategy pattern for your code that creates reports. There's a bagillion ways your could be doing this of course.
I assume the reports are just too extensive, varied, and different in nature that you can't just put sql and styling building block in the db?
Edit based on op's comments:
Ah, gotcha. Well, I don't know how much time you have, but as much as you push everything into some sort of factory, you have better options you'll later. I'm going to give you some thoughts that will hopefully help, from similar things I've done. Each step is an improvement in itself, but also a baby step to really separating your report logic from this shell code. Further, I can see you already know what you're doing and I'm sure know some of what I'll say below, but I don't know what you know, and it will be helpful for others.
First, pull out any and every bit of information from code to db (if you haven't already), and you'll add more db fields (and a table or two) as you improve your setup.
You might know about it already, but I'll mention it for others, to check out the strategy pattern I reference above. You can have the custom logic of each "report function" actually be in the constructor of your various strategy classes. They would all inherit from your base ReportGenerator (or sport a common IReportGenerator interface). They can and should share the same constructor; varying report parameters would be handled by a parameter of type dictionary. Each class's constructor implementation would know the types of the variables is needs (from db configuration), and would cast/use them accordingly.
Next step might be to really get rid of your select statement in your factory, using reflection. You'd have to have the name of the class as part of your reports configuration data in the db (and have a common constructor).
At this point, the way to add a new report is pretty clean, even though you've got to add a new class each time. That good. It fulfills the single responsibility and open-closed principals.
Now, there's just the final step of removing the classes from your app, so they can be added/edited on the fly. Check out MEF. This is what it's made for. Some things you might find on the internet that you probably shouldn't use are CodeDom (great when there was nothing else, but MEF is better) and the compilation-as-a-service features coming in .NET 5. MEF is the way to go.
Assuming that all reports implement IReport, you can do it using Func<IReport>, like this:
IDictionary<string,Func<IReport>> dictToReport = new Dictionary {
{"ReportA", () => CreateReportAReport("ReportA's Title") }
, {"ReportB", () => CreateReportBReport("ReportB's Title") }
, ...
};
You can then replace the switch with this code:
var myReport = dictToReport[Request.QueryString["Report"]]();
I think is better re-design this code and convert it into some database table ("Reports") to keep there the list of reports and ID of each report.
That's it.
To do this with a Dictionary<string, string> you would simply build one up as a static cache in the containing type
public class Container {
private static Dictionary<string, Func<Report>> ReportMap =
new Dictionary<string, Func<Report>>();
static Container() {
ReportMap["ReportA"] = () => CreateReportAReport("ReportA's Title");
ReportMap["ReportB"] = () => CreateReportBReport("ReportB's Title");
// etc ...
}
}
Now that the map is built you simply do a lookup in the function instead of a switch
Func<Report> func;
if (!ReportMap.TryGetValue(Request.QueryString["Report"), out func)) {
// Handle it not being present
throw new Exception(..);
}
Report report = func();

Copying from EntityCollection to EntityCollection impossible?

How would you do this (pseudo code): product1.Orders.AddRange(product2.Orders);
However, the function "AddRange" does not exist, so how would you copy all items in the EntityCollection "Orders" from product2 to product1?
Should be simple, but it is not...
The problem is deeper than you think.
Your foreach attempt fails, because when you call product1.Orders.Add, the entity gets removed from product2.Orders, thus rendering the existing enumerator invalid, which causes the exception you see.
So why does entity get removed from produc2? Well, seems quite simple: because Order can only belong to one product at a time. The Entity Framework takes care of data integrity by enforcing rules like this.
If I understand correctly, your aim here is to actually copy the orders from one product to another, am I correct?
If so, then you have to explicitly create a copy of each order inside your foreach loop, and then add that copy to product1.
For some reason that is rather obscure to me, there is no automated way to create a copy of an entity. Therefore, you pretty much have to manually copy all Order's properties, one by one. You can make the code look somewhat more neat by incorporating this logic into the Order class itself - create a method named Clone() that would copy all properties. Be sure, though, not to copy the "owner product reference" property, because your whole point is to give it another owner product, isn't it?
Anyway, do not hesitate to ask more questions if something is unclear. And good luck.
Fyodor
Based on the previous two answers, I came up with the following working solution:
public static void AddRange<T>(this EntityCollection<T> destinationEntityCollection,
EntityCollection<T> sourceEntityCollection) where T : class
{
var array = new T[sourceEntityCollection.Count()];
sourceEntityCollection.CopyTo(array,0);
foreach (var entity in array)
{
destinationEntityCollection.Add(entity);
}
}
Yes, the usual collection related functions are not there.
But,
1. Did you check CopyTo method?
2. Do you find any problem with using the iterator? You know, GetEnumerator, go through the collection and copy the entities?
The above two can solve your problems. But, I'm sure in .NET 3.0+ there would be compact solutions.
My answers are related to .NET 2.0

C# conventions / best practices

I was wondering is constantly reusing namespace names is valid for c# conventions/best practises.
I am develop most of my programs in Java, and i would have a packet for implementations, eg:
com.ajravindiran.jolt.game.items.sql
com.ajravindiran.jolt.game.users.sql
com.ajravindiran.jolt.events.impl
com.ajravindiran.jolt.tasks.impl
Let's talk about com.ajravindiran.jolt.game.items.sql, which is most close my situation. I current wrote a library that wraps the MySQL Connection/Net into a OODBMS.
So i have an interface called ISqlDataObject which has the following members:
bool Insert(SqlDatabaseClient client);
bool Delete(SqlDatabaseClient client);
bool Update(SqlDatabaseClient client);
bool Load(SqlDatabaseClient client);
and used like such:
public class SqlItem : Item, ISqlDataObject
{
public bool Load(SqlDatabaseClient client)
{
client.AddParameter("id", this.Id);
DataRow row = client.ReadDataRow("SELECT * FROM character_items WHERE item_uid = #id;");
this.Examine = (string)row["examine_quote"];
...
}
...
}
called:
SqlItem item = new SqlItem(int itemid);
GameEngine.Database.Load(item);
Console.WriteLine(item.Examine);
So i was wondering if it's ok to add the sql editions of the items into something like JoltEnvironment.Game.Items.Sql or should i just keep it at JoltEnvironment.Game.Items?
Thanks in adnvanced, AJ Ravindiran.
For naming conventions and rules, see MSDN's Framework Guidelines on Names of Namespaces.
That being said, that won't cover this specific issue:
So i was wondering if it's ok to add the sql editions of the items into something like JoltEnvironment.Game.Items.Sql or should i just keep it at JoltEnvironment.Game.Items?
It is okay to do either, and the most appropriate one depends a bit on your specific needs.
If the game items will be used pervasively throughout the game, but the data access will only be used by a small portion, I would probably split it out into its own namespace (though probably not called Sql - I'd probably use Data or DataAccess, since you may eventually want to add non-SQL related information there, too).
If, however, you'll always use these classes along with the classes in the Items namespace, I'd probably leave them in a single namespace.
You're asking about naming conventions, and the answer is, it's really up to you.
I allow for extra levels of hierarchy in a namespace if there will be multiple implementations. In your case, the .Sql is appropriate if there is some other storage mechanism that doesn't use Sql for queries. Maybe it's XML/Xpath. But if you don't have that, then it seems like the .Sql layer of naming isn't necessary.
At that poiint, though, I'm wondering why you would use {games,users} at the prior level. Feels like the namespace is more naturally
JoltEnvironment.Game.Storage
..And the Fully-qualified type names would be
JoltEnvironment.Game.Storage.SqlItem
JoltEnvironment.Game.Storage.SqlUser
and so on.
If a namespace, like JoltEnvironment.Game.Items, has only one or two classes, it seems like it ought to be collapsed into a higher level namespace.
What are you calling SQL Editions? Versions of SQL Server? Or Version of Database Connections? If the later, I would do something like:
JoltEnvironment.Game.Items.DataAccess.SQLServer
JoltEnvironment.Game.Items.DataAccess.MySQL
JoltEnvironment.Game.Items.DataAccess.Oracle
etc...
If the former, I thought that ADO.NET would take care of that for you anyway, based on the provider, so everything under the same namespace would be ok.

Categories

Resources