How to serialize custom data from database? - c#

I've a table like this :
ID Name Key Value
1 Mydata1 Mail myval1
1 Mydata1 Name myval2
1 Mydata1 Nick myval3
1 Yourdata key2 myval4
and a class like this :
[Serializable]
public class Mydata
{
public string Mail{get;set;}
public string Name{get;set;}
public string Nick{get;set;}
}
I extract from my Table data
where Name = 'MyData1' in a list.
How To serialize this data in my class.
Thanks!

You should look into LINQ to SQL, LINQ to Entities, NHibernate, etc. These are OR Mappers, or Object/Relational Mappers. They are designed to query your database for you, and return serialized objects from your domain. They can greatly reduce the amount of effort it takes to build an application with objects that are persisted to and retrieved from a database server.
Note that Linq to SQL required SQL Server, while the other two can be used with any database.

If you have your class already, you are looking for "POCO" support in an ORM.
E.g. Entities Framework v4 does this. See here for details. I understand nHibernate has this support today.
Alternatively in your data access layer, you can do the conversion in your data access layer (DTO == Data Transfer Object) using a data reader:
var rs = dbCmd.ExecuteReader();
var results = new List<MyDto>();
while (rs.Read()) {
results.Add(new MyDto {
Id = rs.ReadInt("Id"),
Name = rs.ReadString("Name"),
...
};
}
Using LINQ to SQL:
using (var dc = MyDataContext()) {
var results = from d in dc.MyDataType
select new MyDto {
Id = d.Id,
Name = d.Name,
...
};
}
However I tend to add a method to customise the generated entity with a helper method to perform the mapping (which helps avoid repeating the property copy code for each query).

Related

MVC reading from a dynamic list of SQL tables

I have an application that is using MVC framework that currently reads from a model object of a SQL table and puts the results in a list format. The table has its own .cs class with all the necessary fields and the code filters the results based on other factors.
The problem I am running into, is that I need to find a way to add new tables to this list without making changes to the code itself. Ideally, I would like to add a list of tables I need to read from into the web.config and create a class for them in the project structure and the code will dynamically read from that.
Currently with one table the code looks like this:
var assets = _model.FMIF.ToList();
var results = BuildFormatedResult(assets);
And I have been able to add another table to this structure like this:
var assets = _model.FMIF.ToList();
var assets2 = _model.FMHZ.ToList();
assets = assets.Concat(assets2).ToList();
var results = BuildFormatedResult(assets);
I have tried to make this dynamic using a method like this:
var test = "FMIF";
var assets = _model.+test+.ToList();
var results = BuildFormatedResult(assets);
but it does not appear to be able to read the variable as a model.
Is there a best practice way to do something like this? Even if it is way different than what I have tried I am kind of at a loss here. Not super familiar with MVC structure so any help or advice is greatly appreciated.
Thanks!
This is an approach I've used to dynamically get a handle to a DbSet. Firstly I define a couple of methods (This does assume that you have the classes already generated for each of the tables.)
public static DbSet GetDbSet(MyDbContext db, string tableName)
{
// Find the EF entity that corresponds to this table
ObjectContext objectContext = (db as IObjectContextAdapter).ObjectContext;
var mappings = GetEntityMappings(objectContext);
var entityName = mappings[tableName];
// Now get the corresponding DbSet
DbSet dbSet = (DbSet)db.Set(Type.GetType("schema_name." + entityName));
return dbSet;
}
public static Dictionary<string, string> GetEntityMappings(ObjectContext objectContext)
{
var EntityMappings = new Dictionary<string, string>();
// Build a list of database table names to EF entity names
// Get a list of entities
MetadataWorkspace workspace = objectContext.MetadataWorkspace;
var entities = workspace.GetItems<EntityType>(DataSpace.CSpace);
foreach (EntityType et in entities)
{
// Get the entity set that uses this entity type
var entitySet = workspace
.GetItems<EntityContainer>(DataSpace.CSpace)
.Single()
.EntitySets
.Single(s => s.ElementType.Name == et.Name);
// Find the mapping between conceptual and storage model for this entity set
var mapping = workspace.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
.Single()
.EntitySetMappings
.Single(s => s.EntitySet == entitySet);
// Find the storage entity set (table) that the entity is mapped to
var table = mapping
.EntityTypeMappings.Single()
.Fragments.Single()
.StoreEntitySet;
string tableName = (string)table.MetadataProperties["Table"].Value ?? table.Name;
EntityMappings.Add(tableName, et.Name);
}
return EntityMappings;
}
Basically it is poking around in the EntityFramework metadata in order to map a string of a table name to the entity name (which aren't necessarily the same). This is slightly simplified as ideally you would cache the mappings.
Then finally call the GetDbSet() method, I've used AsQueryable() as I potentially need to add where clauses etc.
var dbSet = GetDbSet(db, "table_name").AsQueryable();

How to map Azure Cosmos DB query recordset to C# class object [duplicate]

I'd like to store several different object types in a single Cosmos DB container, as they are all logically grouped and make sense to read together by timestamp to avoid extra HTTP calls.
However, the Cosmos DB client API doesn't seem to provide an easy way of doing the reads with multiple types. The best solution I've found so far is to write your own CosmosSerializer and JsonConverter, but that feels clunky: https://thomaslevesque.com/2019/10/15/handling-type-hierarchies-in-cosmos-db-part-2/
Is there a more graceful way to read items of different types to a shared base class so I can cast them later, or do I have to take the hit?
Thanks!
The way I do this is to create the ItemQueryIterator and FeedResponse objects as dynamic and initially read them untyped so I can inspect a "type" property that tells me what type of object to deserialize into.
In this example I have a single container that contains both my customer data as well as all their sales orders. The code looks like this.
string sql = "SELECT * from c WHERE c.customerId = #customerId";
FeedIterator<dynamic> resultSet = container.GetItemQueryIterator<dynamic>(
new QueryDefinition(sql)
.WithParameter("#customerId", customerId),
requestOptions: new QueryRequestOptions
{
PartitionKey = new PartitionKey(customerId)
});
CustomerV4 customer = new CustomerV4();
List<SalesOrder> orders = new List<SalesOrder>();
while (resultSet.HasMoreResults)
{
//dynamic response. Deserialize into POCO's based upon "type" property
FeedResponse<dynamic> response = await resultSet.ReadNextAsync();
foreach (var item in response)
{
if (item.type == "customer")
{
customer = JsonConvert.DeserializeObject<CustomerV4>(item.ToString());
}
else if (item.type == "salesOrder")
{
orders.Add(JsonConvert.DeserializeObject<SalesOrder>(item.ToString()));
}
}
}
Update:
You do not have to use dynamic types if want to create a "base document" class and then derive from that. Deserialize into the documentBase class, then check the type property check which class to deserialize the payload into.
You can also extend this pattern when you evolve your data models over time with a docVersion property.

Creating Complex Entity Objects

We currently use sp's and udf's to generate an XML document that is sent via web service to the client for consumption. I have used an ORM (Entity and Open Access) before but I alway interacted directly with a single class (table). If I had data that needed to goto multiple tables I would break it apart in code and just update the ORM class (table) the data belonged to.
I am wondering if I can get a bit more complicated. Can I somehow create a complex object in the ORM that is an aggregate of all these fields. In other words I would pass to the constructor of my complex orm object the record key desired. The object would then gather from all the tables the needed info and return to me the object.....which I could then serialize into xml and send on it's way.
I understand that somewhere in the ORM or the DB I have to have the logic to gather all the pieces together so really just looking for input.
If I want an object comprised of data from multiple tables I just add all the tables to the .edmx file. From there I can create a class that gets whatever I want. There's no need for a 1:1 pairing. Within my method to create the object based on say the primary key from TableA you can just do;
Obj GetObj(string primaryKey)
{
dataBase context = new dataBase();
var obj = (from a
in context.TableA
where a.Id == primaryKey
select a);
var otherObj = (from b
in context.TableB
where b.Id == a.ForeignKey
select b);
Obj foo = new Obj();
foo.Id = a.Id;
foo.SomethingElse = a.Somthing;
foo.FromB = b.Id;
foo.AnInt = (int)b.count;
return foo;
}
To save some changes;
void AddNewObject()
{
dataBase context = new Context;
TableA a = new TableA();
TableB b = new TableB();
a.Id = this.Id;
a.OtherField = this.OtherField;
b.Key = this.BKey;
b.SomeInt = this.SomeInt;
context.AddObject("TableA", a);
context.AddObject("TableB", b);
context.SaveChanges();
}
Of course these will need some error handling I haven't included but the concept isn't that different from when you have the standard EntityObject<->Table mapping. I think it's simpler to keep some of the normal mapping then build your class on top of it.

How to specify/filter which table columns should be populated when working with LINQ to SQL?

I'm using LINQ to SQL and have a database table called Product with 20 columns. The Product table is mapped to the Product class in the LINQ to SQL metadata.
I'd like to use my dbContext and retrieve some product records but only populating 10 columns not all 20 columns.
How would that be possible to specify which columns should be returned/populated with LINQ to SQL (or EF)?
I know one way would be using stored procedures but that's this question is about.
Thanks,
You usually use an anonymous class for that:
db.Products.Where(... filter ...).Select(item => new
{
Field1 = item.Field1,
Field2 = item.Field2,
});
Only the fields you include will be selected. If you intend to pass this data structure to other functions or return it, you need a concrete class definition for sub field set, such as:
class SmallerEntity
{
public something Field1;
public something Field2;
}
And you can initialize this in your Select statement:
db.Products.Where(... filter ...).Select(item => new SmallerEntity
{
Field1 = item.Field1,
Field2 = item.Field2,
});
I don't recommend the practice of half-populating an existing class. That makes your state space unnecessarily complex and allows more bugs in your code. Try to contain smaller subsets of data in their own classes.

Deserialize a database table row straight into a C# object - is there a mechanism for this?

I am new to C# and this may end up being a dumb question but i need to ask anyway.
Is there a mechanism with C# to deserialize a result from an executed SQL statement into a c# object?
I have a C# program that reads a table from an sql server storing the row in an object - i am assigning each column value to an object member manually so i was wondering if there is a way to serialize the row automagically into an object. Or even better, a whole table in a collection of objects of the same type.
My environment is C#, VS2010, .NET4, SQLServer2008.
The assumption is that i know the columns i need, it's not a select * query.
A link to a neat example will also be appreciated.
Thanks.
You could use an ORM to do this. ADO.NET Entity Framework (checkout the video tutorials) and NHibernate are popular choices.
If the columns named as per the table names, you can do this with LINQ-to-SQL without any mapping code - just using ExecuteQuery:
using(var dc = new DataContext(connectionString)) {
var objects = dc.ExecuteQuery<YourType>(sql); // now iterate object
}
Additionally, the sql can be automatically parameterized using string.Format rules:
class Person {
public int Id {get;set;}
public string Name {get;set;}
public string Address {get;set;}
}
using(var dc = new DataContext(connectionString)) {
List<Person> people = dc.ExecuteQuery(#"
SELECT Id, Name Address
FROM [People]
WHERE [Name] = {0}", name).ToList(); // some LINQ too
}
Of course, you can also use the VS tools to create a typed data-context, allowing things like:
using(var dc = new SpecificDataContext(connectionString)) {
List<Person> people =
(from person in dc.People
where person.Name == name
select person).ToList();
}

Categories

Resources