Following is the api call that return the Agent object
[Route("GetAgentById")]
public Agent GetAgentById(int id)
{
//Restrict Class fields
return new Agent(id);
}
Agent class have a lot of fields (Let say 100 fields)
public class Agent
{
public int AgentId { get; set; }
public string AgentName { get; set; }
public bool IsAssigned { get; set; }
public bool IsLoggedIn { get; set; }
......
......
public Agent() { }
}
Is there a way to ignore class properties without using annotations. I just want to return some of the fields of agent object before returning the agent object from api call. Is there any way to doing this
Return anonymous object with just required properties, like:
return new { agent.AgentId, agent.AgentName }
or use DTOs (which would be architecturally more correct, specially if you're building complex solution), in this example with Automapper:
return Mapper.Map<AgentDTO>(agent);
But if you really want to use "opt-out" approach and serialize just small subset of your object, and if you're using JSON.NET, you can mark just properties which needs to be serialized:
[DataContract]
public class Agent
{
// included in JSON
[DataMember]
public int AgentId { get; set; }
[DataMember]
public string AgentName { get; set; }
// ignored
public bool IsAssigned { get; set; }
public bool IsLoggedIn { get; set; }
}
Related
I am currently working on making viewmodels capable of parsing data extracted from database to the UI and vice versa, and to do so I do a lot of manual mapping between my two viewmodels.
Currently I try to pass some values that determines an attribute, but since each attributetype requires specifying a lot specific parameter, and 90% of the variables will be redundant in all cases since attributes only have one type..
Thus i have create a placeholder base class, which just contains an Id, that each atttribute have,
and each of the specific attribute type parameter will then use this placeholder as base class..
example:
public class BooleanViewSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeViewSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class AttributeView
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeViewSpecification { get; set; }
}
And the same Goes for my DB view model
public class BooleanSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class Attribute
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeSpecification { get; set; }
}
Problem is then mapping from one class to another class
public static IEnumerable<AttributeView> MapToViewModel(this IEnumerable<Attribute> attributes)
{
return attributes.Select(z => new AttributeView()
{
Type = z.Type,
AttributeTypeViewSpecification = z.AttributeTypeSpecification
});
}
Which does not seem to work?
I use entity framework and migrate using Code-First what I receive is the Id of the location, and not the actual values?
I cant seem to understand why I cant be given the values - if it during the mapping does have the value?
So why cant they be mapped over?
I retrieve the value
Context.Include(Attribute).ThenInclude(AttributeTypeSpecification)
The only thing I receive is the actual Id rather than the specified entries?
My goal is to create the poco classes without knowing which ORM is going to be used.
Now observe the following code...
public class NeuralModel
{
public NeuralModel()
{
Configurations = new HashSet<NeuralModelConfiguration>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime? LastTrained { get; set; }
//Navigation properties
public ICollection<NeuralModelConfiguration> Configurations { get; set; }
//NotMapped properties
[NotMapped]
public NeuralModelConfiguration DefaultConfiguration { get { return Configurations.SingleOrDefault(config => config.IsDefault); } }
[NotMapped]
public bool IsTrained { get { return LastTrained.HasValue; } }
}
public class NeuralModelConfiguration
{
public NeuralModelConfiguration()
{
KeyValues = new HashSet<KeyValuePair<string, string>>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsDefault { get; set; }
public ICollection<KeyValuePair<string, string>> KeyValues
public int ModelId { get; set; }
//Navigation properties
public NeuralModel Model { get; set; }
}
Now suppose if I were to use Entity Framework Core, I get into the issue of mapping complex types (in my example it would be ICollection<KeyValuePair<string, string>>).
According to my research I came across two possible solutions:
Serialization
Another Entity
Now my question is that is there a third solution that do not require me to change my poco classes but rather do some sort of hidden processing at the dbcontext level?
Should there not be a third solution then out of the 2 available solutions which one would be considered better in terms of performance?
I am thinking designing a field in db that stores the Serialized Object. When I call that property in entity, that returns String property which is obvious. I am looking for a way to attach a property dynamically and assign the deserialized object to the Class instance. Can any one suggest the best possible way?
DB Structure
Users Table
UserId ..... ..... ..... UserNotes (nvarchar)
Class Structure
[Serializable]
[XmlRoot("Notes")]
public class GenericNotes {
public DateTime Date {
get;
set;
}
public String CommentBy {
get;
set;
}
public string Type {
get;
set;
}
public string Comment {
get;
set;
}
}
public class Users {
public UserId int {
get;
set;
}
public string UserNotes {
get;
set;
}
// I dont have the following definition in the class because its coming from entity framework.
//But I want the following property attached to the class on runtime.
//I will take care of of deserializing using extension methods or some sort methods.
public string List < GenericNotes > NotesCollection {
get;
set;
}
}
Instead of property you can have extension method to do this
public static class UserExtension
{
public static List<GenericNotes> GetNotes(this Users users)
{
//return your deserialized GenericNotes from string
}
}
Then you can use this anywhere like
List<GenericNotes> notes = users.GetNotes();
Let me give a great example which will illustrate my problem.
Let's say I am building an application where many users can post different type of 'posts' (i.e. Photo, Status, etc). Let's just use Photo and Status for this case.
I will show you how I am currently modeling my data, and if this can be improved (and what I am doing wrong)
I have a generic Post class:
public class Post<T>
{
public Guid Id { get; set; }
public User Owner { get; set; }
public DateTime CreatedDate { get; set; }
public PostType Type { get; set; }
public T Data { get; set; }
}
Then I have a PostType enum:
public enum PostType
{
Photo,
Status
}
Then I have my respective Photo and Status classes
public class Photo
{
public string Url { get; set; }
public int Width { get; set; }
public int Height { get; set; }
}
public class Status
{
public string Text { get; set; }
}
I know that if I pursue my current solution to modeling this data, I will run into problems.
I have already hit some pain points, such as how do I return the latest 25 posts, regardless of type and also how do I return a specific post by Id without specifying the type of post(because the user shouldn't care.
Am I modeling my data COMPLETELY incorrectly? If so, do you have any suggestions for improvement?
Both of your problems could be solved by having a base class independent of the post type:
public abstract class Post
{
public Guid Id { get; set; }
public User Owner { get; set; }
public DateTime CreatedDate { get; set; }
public PostType Type { get; set; }
}
Your Post class can then inherit from it:
public class Post<T> : Post
{
public T Data { get; set; }
}
The methods that should return any type of post can still return the correct type but the caller will access them as the base Post type and cast them when needed:
Post GetPostById(int id);
IEnumerable<Post> GetLatestPosts(int count);
how do I return the latest 25 posts, regardless of type
You can't, because in your design there is nothing common between a Photo and a Status, your have a generic Post<T>, but here Ts can't be proceeded in a batch. A better design would be something like this:
public interface IPostable
{
Guid Id { get; set; }
public DateTime CreatedDate { get; set; }
PostType PostType { get; }
}
public class Photo : IPostable
{
//special properties for photo
public string Url { get; set; }
//implement the interface
public PostType PostType { get { return PostType.Photo; } }
}
public class Status : IPostable
{
public string Text { get; set; }
public PostType PostType { get { return PostType.Status; } }
}
Then you always deal with IPostable in a batch.
how do I return a specific post by Id
According to the design above, you can easily get a IPostable instance by its id, since id is one of its property, and return strongly-typed instance by judging its PostType property:
public IPostable GetPost(Guid id)
{
//id is a property of IPostable, so everything is easy
}
//you can easily get the real type
public T GetPost<T>(Guid id)
{
IPostable post = GetThePostFirst();
if (post.PostType == PostType.Photo) return (Photo)IPostable;
//etc.
}
I have two POCO classes (Account and Invoice) and as you can see (below are mockups of these classes) they are recursive.
When I pass in an invoice object with the account property set and then try to store it using the redis client it causes a stackoverlow due to recursion. Below is an example of how I'm making the call.
CachingService.Store<Invoice>(invoiceObj);
public class CachingService {
// ....
public static void Store<T>(T obj)
{
using (var client = _redisClientsManager.GetClient())
{
var typedClient = client.GetTypedClient<T>();
typedClient.Store(obj);
}
}
}
Example of my POCO classes:
public class Account
{
public string Name { set; get; }
public bool IsActive { set; get; }
public virtual ICollection<Invoice> Invoices { set; get; }
}
public class Invoice
{
public bool IsPaid { set; get; }
public DateTime? LastSent { set; get; }
public int AccountId { set; get; }
public virtual Account Account { set; get; }
}
Most serializers (ServiceStack included) does not support cyclical references. This is a major anti-pattern when designing DTOs.
To resolve this, you want to tell ServiceStack.Text's serializers to ignore that property for Serialization which you can do using the [IgnoreDataMember] property or changing it so it's not a public property or change it into a method.