I realize there are loads of questions already posted regarding serialization of ADO.Net entities, but I haven't had any luck finding one that really addresses quite what I want to do.
Basically, I need a really bare-bones, shallow JSON or plain-object representation of an ADO.Net entity. The purpose is for change-logging; i.e. when a record is going to be changed, I want to snag a copy of its data "before" and "after", and log the change.
I don't want any of the navigation, complex or other properties to be considered; just the scalar properties of the entity. If I miss some data that only would appear in special cases, that's fine -- just trying to do a rough log. Ideally my final code should look something like this:
Employee emp = db.Employees.First();
string oldRecordJSON = MySerializer.serialize(emp);
emp.Name = "Fred";
db.saveChanges();
string newRecordJSON = MySerializer.serialize(emp);
ChangeLog.logDBChange("Employees", emp.ID, oldRecordJSON, newRecordJSON, DateTime.Now);
...Any quick & easy way to implement MySerializer.serialize?
Thanks!
If you're just wanting some specific properties of your employee, consider creating a basic model and serialising that.
var serializer = new JavaScriptSerializer();
serializer.Serialize(new MyEmployeeModel{ // set fields here});
You can build this as a converter if you wish, that's how I'd do it.
I have an interface, IConverter<TInputType, TOutputType> from which you can create a converter to inject (or whatever you want to do) into your code.
public interface IEmployeeFromDatabaseToBasicEmployeeModelConverter
: IConverter<TheDBType, MyEmployeeModel>{}
public class EmployeeFromDatabaseToBasicEmployeeModelConverter :
IEmployeeFromDatabaseToBasicEmployeeModelConverter
{
public MyEmployeeModel Invoke(TheDBType myDbTypeObject)
{
return new MyEmployeeModel{
// set properties.
}
}
}
Related
I have this model
public class model
{
public string at1{set; get;}
public string at2{set; get;}
public string at2{set; get;}
public string at2{set; get;}
public string at2{set; get;}
};
I make an instance of model like:
List<model> md= new List<model>();
then I write a query like this from a table with same names as model is
md = db.SomeTable.Where(a => a.at1 == '1').Select (row => new model()).ToList()
What I am seeking is put whole of any row in SomeTable into model's format.
Obviously my code isn't working and return null data and if change it like this, it works
md = db.SomeTable.Where(a => a.at1 == '1').Select (row => new model
{
at1=a.at1,
at2=a.at2,
at3=a.at3,
at4=a.at4,
at5=a.at5,
).ToList()
I dont want to put every attribute name in my query, Is there any substitute?
Note: I dont want to use Model of Database I mean (SomeTable's Model)
I want to receive result of query in another model.
(Because of join, include, etc)
I cant comment yet so posting as an answer.
+1 on using #MindSwipe's Automapper if you can. Where I work we use Automapper to take the information from an api response object and map it to the view model properties. Super easy to use if your objects are similar in structure. You can also extend it for more complicated structures.
I've also come across practices in Dart/Flutter where Classes have a map function where you can pass a json string for eg and it maps the relevant information across.
(NOT RECOMMENDED!!)This option might also leave you vulnerable to potential runtime issues etc. The final option I can think of is to use something like Reflection to create a generic function where you have to go through the properties between class A and class B and if the names match then set the value. That said I have a feeling Automapper might be doing this/something similar under the hood, so why reinvent the wheel I guess.
The product have some fields that can not be changed,
so I want to bind the object with only selected field.
For now I'm doing this(below) way (like binding manually), but I believe there is better and clean way. How to binding Model object to model object with only selected fields?
[HttpPut]
public JsonResult update(Product editedProduct) {
Product originalProduct = unitOfWork.ProductRepository.Get(filter: q => q.no == editedProduct.no).Single();
originalProduct.name = editedProduct.name;
originalProduct.modelNo = editedProduct.modelNo;
originalProduct.size = editedProduct.size;
originalProduct.color = editedProduct.color;
originalProduct.description = editedProduct.description;
originalProduct.price = editedProduct.price;
//originalProduct.upc = editedProduct.upc; //UPC can not be changed
//originalProduct.sku = editedProduct.sku; //SKU can not be changed
unitOfWork.Save();
return Json(new { success = true });
}
please advise me,
In my opinion there is absolutely nothing wrong with this approach. It is possible to do some things differently but it does not mean it is better.
Create a DTO/ViewModel class to represent the class you accept and return from the service. This way you can have different shapes of the data if you need it. For example you can skip a security critical field. I think this will be an improvement.
Use a framework like AutoMapper to do the mapping between the objects. This is quite popular approach but I personally prefer explicitly copying the fields.
You can update the object without retrieving it. I assume you are using Entity Framework. You can refer to this question for details - How to update a record without selecting that record again in ADO.NET Entity Framework? . I personally don't think that this will improve your code. I think you should do it only if you have performance issues with your current approach.
You can put the mapping code in your repository in an Update method or something.
BTW it seems like your repository is currently useless. You are just writing a wrapper around your ORM which makes the code more complex and more buggy. Repository is an anti-pattern when you are using an ORM. Your ORM is the repository.
Well, don't do it.
For this case you should create a separate ViewModel with only necessary fields.
I would not expose the setter in the class for example.
public class Product{
public string upc {get;}
}
This will not allow the property to be set.
I've just read about the repository pattern in c#. It will provide an interchangeable layer for how the actual data is accessed. That's great. However, consider the following:
I have an XmlPersonRepository which will fetch XML data from a file and return it as a c# object (Person.cs POCO). Now I want the physical source of the XML data to be interchangeable too. Originally, it comes from a file, but it can also come from a web server or from a resource string. How would I implement this in the most reusable way? I don't want to write something like XmlPersonFromFileRepository and a XmlPersonFromWebRepository, because it would mean code duplication. It would duplicate the code for converting the raw XML data into a c# object, but this code stays the same, no matter if i fetch XML from a file or from a web service. So it's redundant to have the conversion code in both classes.
So in a nutshell, I want to have two abstraction layers: One layer which fetches the psysical XML data from whatever source, and another layer which converts this data into c# objects. Both should be interchangeable.
How can I implement this? And please tell me if this is a good idea or not, am I on the right track?
Simple. You just worded it in your question.
You have two problems to solve:
Get XML data from a source
Convert XML data to C# Object
To implement the first problem:
- IXmlDataGetter, an interface getting a single XML data from a source.
public interface IXmlDataGetter {
XmlData GetData(XmlDataName name);
}
"XmlData" should be either a byte[] or a Stream (Because XML contains metadata with regards to the encoding of data, I think it should be kept at byte level) or be a DOM Tree (like XmlNode). You choose the solution that fits you best.
"XmlDataName" is the way you identify a your stored data. Data has a name, however complex it may be. It may be just the string "PERSON" and the integer 25, being the id. The name of the data for the person with ID 25 may be the pair ("PERSON", 25).
This interface, can be implemented for DB:
public class DBXmlDataGetter : IXmlDataGetter {
XmlData GetData(XmlDataName name) {
return ResultOfQuery("SELECT xml_text FROM " + name.first /* PERSON */ + " WHERE ID=" + name.second /* 25 */);
}
}
This interface can also be implemented for a file:
public class FileXmlDataGetter : IXmlDataGetter {
XmlData GetData(XmlDataName name) {
return ContentsOfFile(name.first /* PERSON */ + "_" + name.second /* 25 */ + ".xml");
}
}
Of course "ResultOfQuery" and "ContentsOfFile" are just names of things I leave it to you to solve. And for the Web, build your URL from your XmlDataName the same way.
Now. Second problem, converting XML to C# object. You may use an XMLDeserializer, or parse the data with an XMLReader and build your object explicitly. You just have to create a class that does te job and takes the appropriate strategy as a constructor parameter:
public class XmlPersonRepository {
private readonly IXmlDataGetter _getter;
public PersonFetcher(IXmlDataGetter getter) {
_getter = getter;
}
Person GetFromId(int id) {
var xmlData = _getter.GetData(new XmlDataName("PERSON", id));
return ConvertToPerson(xmlData);
}
}
I won't get into the philosophical questions of IoC/Dependency injection here, but this is the basic pattern. The class that does the conversion just does the conversion. All it needs to perform the use case from end to end gets "injected" from "above".
You separated the responsibilities, now you're free to get your XML data from a user copy/paste in a textbox if you wish.
As said, check what Dependency Injection/Ioc is and have a look to some of the frameworks out there (like Ninject, Autofac etc).
In a nutshell you should create an interface IXmlPersonRepository that defines your methods and then implement it on all the different classes that will provide you the xml like
XmlFilePersonRepository : IXmlPersonRepository
XmlDBPersonRepository : IXmlPersonRepository
and so on.
You will then use the interface IXmlPersonRepository to do your calls. The DI bit will be responsible of the concrete implementation of your interface and it will be easy to swap between db, file etc.
I have several navigation properties from a 'Users' table to a 'Reports' table. The navigation properties that are generated are obviously accessed like this:
USER.REPORTs.Where(x => ...)
USER.REPORTs2.Where(x => ...)
USER.REPORTs3.Where(x => ...)
The first one is user createdId, second UserApprovedId etc... basic stuff.
These are extremely difficult to interpret. Its difficult to tell which property you are navigating without accessing the EDMX and checking the navigation property.
Now I know I can create my own End1/End2 navigation properties the properties manager but these are lost if the Model is recreated.
Is there a way around this?
I have not tried this, but here's an idea: since all the entity types are partial classes why not wrap the navigation property generated by Visual Studio in another property with a convenient name?
In your designer file you'll have something like this:
public partial class MyEntity : EntityObject
{
#region Navigation Properties
public EntityCollection<MyOtherEntity> Other_Entities1
{
// ...
}
#endregion
}
You can then create another file in which to wrap the navigation property:
public partial class MyEntity
{
public EntityCollection<MyOtherEntity> OtherEntities
{
get { return Other_Entities1;}
}
}
You'll use the property above throughout your code and since the same logic is used when Visual Studio generates the .edmx file the wrapped property won't change.
Even if the wrapped property will change its name you'll need to adjust the code in a single place.
I'm not sure if I'm understanding your problem correctly, but it sounds like you just want a "cleaner" way to access the results of a REPORTs.Where(...) LINQ query directly from the USER object. If that is the case, I suggest creating extensions of the USER object like this:
public static class UserExtensions
{
public static List<REPORT> ReportsWithSomeCondition(this USER user)
{
return user.REPORTs.Where(...).ToList();
}
}
And the way you can cleanly call this is:
List<REPORT> results = USER.ReportsWithSomeCondition()
If I totally missed the point, please clarify your question and I will delete this answer.
I think i have the same problem as i understand from your question.
You want to keep your navigational properties names as clear as you can but whenever recreate your Model from edmx ?!.
Actually i hope if there is a better solution but here what I'm doing :
Name your relations in DataBase a good names like : FK_Users_CreateUserReport, FK_Users_ApprovedUserReport ... or any suitable names we'll then rename the navigational properties as ApprovedUserReport and CreateUserReport so on ...
make a helper code to execute whenever you recreate your Model and this code will open your edmx file and makes update to all navigational properties you want something like this:
// file here is the path to your edmx file
if (!string.IsNullOrEmpty(file))
{
var ns = XNamespace.Get("http://schemas.microsoft.com/ado/2008/09/edm");
var doc = XDocument.Load(file);
var list = (from xElem in doc.Descendants(ns + "NavigationProperty")
where xElem.Attribute("Name").Value.StartsWith("REPORTs"))
select xElem).ToList();
foreach (var item in list)
{
var newName = item.Attribute("Relationship").Value.Split('_').LastOrDefault();
if (!newName.Contains("."))
item.SetAttributeValue("Name", newName);
else
{
var ss = newName.Split('.').LastOrDefault();
}
}
doc.Save(file);
MessageBox.Show(list.Count.ToString());
}
Final thing if you used Code Only pattern then this problem is gone but in that case you should keep your Model in agreement with your DataBase by hand.
You have to put all your custom entity code in separate code files using the partial class mechanism. This allows the generated code to be generated without your custom code to be affected.
Wahid's answer seems to be the best one for long term maintenance. We considered implementing interface properties in the Partial Class we use as a "Buddy Class" for extensions and setting up Metadata linking. But then the properties in the T4 template we are Interfacing would still be public and they should be private.
To improve upon Wahid's suggestion; we chose to instead of changing the standard of how we name Foreign key relationships, extend them.
FK_Users_Report_CreateUserReport would actually be our solution. The standard naming convention for the first 2 values is maintained and in the update model code you can force it to only change the navigation property names of ones with the 3rd underscore and 3rd value on it. Ensuring you do no effect anyone other navigation property names if they didn't follow the standard naming convention for Foreign Keys in the DB.
One of my fellow developer has a code similar to the following snippet
class Data
{
public string Prop1
{
get
{
// return the value stored in the database via a query
}
set
{
// Save the data to local variable
}
}
public void SaveData()
{
// Write all the properties to a file
}
}
class Program
{
public void SaveData()
{
Data d = new Data();
// Fetch the information from database and fill the local variable
d.Prop1 = d.Prop1;
d.SaveData();
}
}
Here the Data class properties fetch the information from DB dynamically. When there is a need to save the Data to a file the developer creates an instance and fills the property using self assignment. Then finally calls a save. I tried arguing that the usage of property is not correct. But he is not convinced.
This are his points
There are nearly 20 such properties.
Fetching all the information is not required except for saving.
Instead of self assignment writing an utility method to fetch all will have same duplicate code in the properties.
Is this usage correct?
I don't think that another developer who will work with the same code will be happy to see :
d.Prop1 = d.Prop1;
Personally I would never do that.
Also it is not the best idea to use property to load data from DB.
I would have method which will load data from DB to local variable and then you can get that data using property. Also get/set logically must work with the same data. It is strange to use get for getting data from DB but to use set to work with local variable.
Properties should really be as lightweight as possible.
When other developers are using properties, they expect them to be intrinsic parts of the object (that is, already loaded and in memory).
The real issue here is that of symmetry - the property get and set should mirror each other, and they don't. This is against what most developers would normally expect.
Having the property load up from database is not recommended - normally one would populate the class via a specific method.
This is pretty terrible, imo.
Properties are supposed to be quick / easy to access; if there's really heavy stuff going on behind a property it should probably be a method instead.
Having two utterly different things going on behind the same property's getter and setter is very confusing. d.Prop1 = d.Prop1 looks like a meaningless self-assignment, not a "Load data from DB" call.
Even if you do have to load twenty different things from a database, doing it this way forces it to be twenty different DB trips; are you sure multiple properties can't be fetched in a single call? That would likely be much better, performance-wise.
"Correct" is often in the eye of the beholder. It also depends how far or how brilliant you want your design to be. I'd never go for the design you describe, it'll become a maintenance nightmare to have the CRUD actions on the POCOs.
Your main issue is the absense of separations of concerns. I.e., The data-object is also responsible for storing and retrieving (actions that need to be defined only once in the whole system). As a result, you end up with duplicated, bloated and unmaintainable code that may quickly become real slow (try a LINQ query with a join on the gettor).
A common scenario with databases is to use small entity classes that only contain the properties, nothing more. A DAO layer takes care of retrieving and filling these POCOs with data from the database and defined the CRUD actions only ones (through some generics). I'd suggest NHibernate for the ORM mapping. The basic principle explained here works with other ORM mappers too and is explained here.
The reasons, esp. nr 1, should be a main candidate for refactoring this into something more maintainable. Duplicated code and logic, when encountered, should be reconsidered strongly. If the gettor above is really getting the database data (I hope I misunderstand that), get rid of it as quickly as you can.
Overly simplified example of separations of concerns:
class Data
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
}
class Dao<T>
{
SaveEntity<T>(T data)
{
// use reflection for saving your properies (this is what any ORM does for you)
}
IList<T> GetAll<T>()
{
// use reflection to retrieve all data of this type (again, ORM does this for you)
}
}
// usage:
Dao<Data> myDao = new Dao<Data>();
List<Data> allData = myDao.GetAll();
// modify, query etc using Dao, lazy evaluation and caching is done by the ORM for performance
// but more importantly, this design keeps your code clean, readable and maintainable.
EDIT:
One question you should ask your co-worker: what happens if you have many Data (rows in database), or when a property is a result of a joined query (foreign key table). Have a look at Fluent NHibernate if you want a smooth transition from one situation (unmaintainable) to another (maintainable) that's easy enough to understand by anybody.
If I were you I would write a serialize / deserialize function, then provide properties as lightweight wrappers around the in-memory results.
Take a look at the ISerialization interface: http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx
This would be very hard to work with,
If you set the Prop1, and then get Prop1, you could end up with different results
eg:
//set Prop1 to "abc"
d.Prop1 = "abc";
//if the data source holds "xyz" for Prop1
string myString = d.Prop1;
//myString will equal "xyz"
reading the code without the comment you would expect mystring to equal "abc" not "xyz", this could be confusing.
This would make working with the properties very difficult and require a save every time you change a property for it to work.
As well as agreeing with what everyone else has said on this example, what happens if there are other fields in the Data class? i.e. Prop2, Prop3 etc, do they all go back to the database, each time they are accessed in order to "return the value stored in the database via a query". 10 properties would equal 10 database hits. Setting 10 properties, 10 writes to the database. That's not going to scale.
In my opinion, that's an awful design. Using a property getter to do some "magic" stuff makes the system awkward to maintain. If I would join your team, how should I know that magic behind those properties?
Create a separate method that is called as it behaves.