I'm trying to cast a complex Entity to a Dto. I would like to remove some values which are in the entity from the DTO.
My entity looks like this (For simplicity a large part of the entity is omitted):
export class ResultEntity {
constructor(
public id: string,
public userId: string,
public results: CalculationOutputEntity[] = [],
public item: Item = new Item(),
) { }
}
export class Item {
constructor(
public privat: Private = new Private(),
public state: State = new State(),
public combined: number = 0,
) { }
}
export class State {
constructor(
public numberA: number = 0,
public numberB: number = 0,
public numberC: number = 0,
public numberD: number = 0,
) { }
}
I have found a solution which works very well for simple entities: Cast entity to dto
If I adopt this suggestion of the custom interceptor, removing the id or the whole item property works.
I have tried two possibilities tot define my DTOs:
It returns only the id and the item as a whole.
#Exclude()
export class AdvisoryResultDto {
#Expose()
public id: string;
public userId: string;
public results: CalculationOutputDto[];
#Expose()
public item: Item;
}
This solution returns everything except the item property.
export class AdvisoryResultDto {
public id: string;
public userId: string;
public results: CalculationOutputDto[];
#Exclude()
public item: Item;
}
The problem now is that I want to remove only certain values within the item property. So for example the private field and within the state-property numberB.
I would like to have the possibility within the nested classes to remove single values also with Exclude().
So for example:
export class AdvisoryResultDto {
public id: string;
public userId: string;
public results: CalculationOutputDto[];
public item: Item;
}
export class Item {
#Exclude()
public privat: PrivateDto;
public state: StateDto;
public combined: number;
}
export class StateDto {
public numberA: number;
#Exclude()
public numberB: number;
public numberC: number;
public numberD: number;
}
Unfortunately I can't find anything about this exact problem. To take over the mapping manually would also not be a solution, since the CalculationOutput is by far more complex and is nested with many classes and properties.
Am I just missing a small step or is it not possible with Expose and Exclude from the class-transformer? If not I would appreciate another solution.
So i found the soulution in the documentation of the class-transformer package: https://github.com/typestack/class-transformer#working-with-nested-objects
I need to add the #Type-Decorator to nested classes
The solution:
#Expose()
export class AdvisoryResultDto {
public id: string;
public userId: string;
public results: CalculationOutputDto[];
#Type(() => Item)
public item: Item;
}
export class Item {
#Exclude()
#Type(() => PrivateDto)
public privat: PrivateDto;
#Expose()
#Type(() => StateDto)
public state: StateDto;
public combined: number;
}
export class StateDto {
public numberA: number;
#Exclude()
public numberB: number;
public numberC: number;
public numberD: number;
}
Why not make a constructor and then initalize DTO with only the required values from the entity? Just pass the entity object to DTO's constructor and remove the fields from DTO.
Related
Suppose I have a business object: (C#)
public class ModelA {
public int id {get;set;}
[Required, MyCustomAttribute(...)]
public string str {get;set;}
}
Then I have a ModelAController: (C#)
[Route("api/[controller]")]
[ApiController]
public class ModelAController : Controller
{
// ... some contructors and readonly database ...
[HttpPut("read")]
public ActionResult<ModelA> Read() {
return db.Read<ModelA>();
}
}
Then I have some Vue component: (vue.js)
import ...
export default {
data () {
return {
annotations: '',
model: '',
};
},
created: function()
{
this.values = Read('ModelA'); // reads data in json format returned by ModelAController.Read()
this.annotation = // ?????
},
};
My question is; From a Vue component, how do I access the annotations "Required" and "MyCustomAttribute" and others. Should I add a method in my controller to get these Attribute?
[HttpPut("attributes")]
public ActionResult<Attribute[]> Attributes(string propertyName) {
return getAttributesOf(propertyName);
// getAttributesOf("str") would return Attribute[]{ RequiredAttribute, MyCustomAttribute(...)}
}
Is there a better way?
I created 2 entities User and Photo with relations. When I try to find all data of User with it's relations, I get this error:
TypeError: Cannot read property 'joinColumns' of undefined
It works fine as soon as I remove my Getter & Setter and set the properties to public access and removing the underscore. But I want to keep Getters & Setters actually.
user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { Photo } from './photo.entity';
#Entity()
export class User {
#PrimaryGeneratedColumn({ name: 'id' })
private _id: number;
#Column({ name: 'name' })
private _name: string;
#OneToMany(type => Photo, photo => photo.user)
private _photos: Photo[];
public get id(): number {
return this._id;
}
public set id(value: number) {
this._id = value;
}
public get name(): string {
return this._name;
}
public set name(value: string) {
this._name = value;
}
public get photos(): Photo[] {
return this._photos;
}
public set photos(value: Photo[]) {
this._photos = value;
}
}
photo.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user.entity';
#Entity()
export class Photo {
#PrimaryGeneratedColumn({ name: 'id' })
private _id: number;
#Column({ name: 'url' })
private _url: string;
#ManyToOne(type => User, user => user.photos)
private _user: User;
public get id(): number {
return this._id;
}
public set id(value: number) {
this._id = value;
}
public get url(): string {
return this._url;
}
public set url(value: string) {
this._url = value;
}
public get user(): User {
return this._user;
}
public set user(value: User) {
this._user = value;
}
}
user.repository.ts
public async findUsers(): Promise<User[]> {
return await this.find({ relations: ['_photos'] }); // photos (without _) isn't working as well
}
Is there a way to map fields from classes to one using Orika.
Can't find the solution in the orika documentation.
In the example the fields test & name from class ObjectOne should be mapped to the corresponding fields ObjectNew.
public class ObjectOne {
private String test;
private String name;
private String id;
public ObjectOne(String id,String test, String name){
this.id=id;
this.test=test;
this.name=name;
}
}
The same with field sheet from ObjectTwo
public class ObjectTwo {
private String sheet;
private String id;
public ObjectTwo(String id,String sheet){
this.id=id;
this.sheet=sheet;
}
}
Code for ObjectNew
public class ObjectNew {
private String id;
private String test;
private String name;
private String sheet;
public ObjectNew(String id,String test,String name,String sheet){
this.id=id;
this.test=test;
this.name = name;
this.sheet = sheet;
}
}
Fields from both classes ObjectOne & ObjectTwo should initiate new object ObjectNew when id's of classes ObjectOne and ObjectTwo are the same.
Any ideas how to handle this?
Kind Regards
I would suggest to wrap the source objects into one source wrapper object and map this new wrapper object with your new object:
public class objectWrapper{
private objectOne objectOne;
private objectTwo objectTwo;
}
I am using asp.net mvc 5 and C# with Entity Framework... I have model and domain classes for function... now I need to use stored procedure.... which I am struggling at the movement.
I am following code first existing database and I have stored procedure written there. My question is how I can call that stored procedure in my web application.
Stored procedure:
ALTER PROCEDURE [dbo].[GetFunctionByID](
#FunctionId INT
)
AS
BEGIN
SELECT *
FROM Functions As Fun
WHERE Function_ID = #FunctionId
END
Domain class:
public class Functions
{
public Functions()
{
}
public int Function_ID { get; set; }
public string Title { get; set; }
public int Hierarchy_level { get; set; }
}
Function model:
[Table("Functions")]
public class App_Functions
{
public App_Functions()
{
}
[Key]
public int Function_ID { get; set; }
[StringLength(50)]
[Required]
public string Title { get; set; }
public int Hierarchy_level { get; set; }
//public virtual ICollection<App_Controllers> App_Controllers { get; set; }*/
}
BaseContext:
public class BaseContext<TContext> : DbContext where TContext : DbContext
{
static BaseContext()
{
Database.SetInitializer<TContext>(null);
}
protected BaseContext()
: base("name = ApplicationDbConnection")
{ }
}
Function context:
public class FunctionsContext : BaseContext<FunctionsContext>
{
public DbSet<App_Functions> Functions { get; set; }
}
You need to create a model class that contains all stored procedure properties like below.
Also because Entity Framework model class needs primary key, you can create a fake key by using Guid.
public class GetFunctionByID
{
[Key]
public Guid? GetFunctionByID { get; set; }
// All the other properties.
}
then register the GetFunctionByID model class in your DbContext.
public class FunctionsContext : BaseContext<FunctionsContext>
{
public DbSet<App_Functions> Functions { get; set; }
public DbSet<GetFunctionByID> GetFunctionByIds {get;set;}
}
When you call your stored procedure, just see below:
var functionId = yourIdParameter;
var result = db.Database.SqlQuery<GetFunctionByID>("GetFunctionByID #FunctionId", new SqlParameter("#FunctionId", functionId)).ToList());
After importing stored procedure, you can create object of stored procedure pass the parameter like function
using (var entity = new FunctionsContext())
{
var DBdata = entity.GetFunctionByID(5).ToList<Functions>();
}
or you can also use SqlQuery
using (var entity = new FunctionsContext())
{
var Parameter = new SqlParameter {
ParameterName = "FunctionId",
Value = 5
};
var DBdata = entity.Database.SqlQuery<Course>("exec GetFunctionByID #FunctionId ", Parameter).ToList<Functions>();
}
You can call a stored procedure using SqlQuery (See here)
// Prepare the query
var query = context.Functions.SqlQuery(
"EXEC [dbo].[GetFunctionByID] #p1",
new SqlParameter("p1", 200));
// add NoTracking() if required
// Fetch the results
var result = query.ToList();
// Add some tenants to context so we have something for the procedure to return!
AddTenentsToContext(Context);
// ACT
// Get the results by calling the stored procedure from the context extention method
var results = Context.ExecuteStoredProcedure(procedure);
// ASSERT
Assert.AreEqual(expectedCount, results.Count);
}
Mindless passenger has a project that allows you to call a stored proc from entity frame work like this....
using (testentities te = new testentities())
{
//-------------------------------------------------------------
// Simple stored proc
//-------------------------------------------------------------
var parms1 = new testone() { inparm = "abcd" };
var results1 = te.CallStoredProc<testone>(te.testoneproc, parms1);
var r1 = results1.ToList<TestOneResultSet>();
}
... and I am working on a stored procedure framework (here) which you can call like in one of my test methods shown below...
[TestClass]
public class TenantDataBasedTests : BaseIntegrationTest
{
[TestMethod]
public void GetTenantForName_ReturnsOneRecord()
{
// ARRANGE
const int expectedCount = 1;
const string expectedName = "Me";
// Build the paraemeters object
var parameters = new GetTenantForTenantNameParameters
{
TenantName = expectedName
};
// get an instance of the stored procedure passing the parameters
var procedure = new GetTenantForTenantNameProcedure(parameters);
// Initialise the procedure name and schema from procedure attributes
procedure.InitializeFromAttributes();
// Add some tenants to context so we have something for the procedure to return!
AddTenentsToContext(Context);
// ACT
// Get the results by calling the stored procedure from the context extention method
var results = Context.ExecuteStoredProcedure(procedure);
// ASSERT
Assert.AreEqual(expectedCount, results.Count);
}
}
internal class GetTenantForTenantNameParameters
{
[Name("TenantName")]
[Size(100)]
[ParameterDbType(SqlDbType.VarChar)]
public string TenantName { get; set; }
}
[Schema("app")]
[Name("Tenant_GetForTenantName")]
internal class GetTenantForTenantNameProcedure
: StoredProcedureBase<TenantResultRow, GetTenantForTenantNameParameters>
{
public GetTenantForTenantNameProcedure(
GetTenantForTenantNameParameters parameters)
: base(parameters)
{
}
}
If either of those two approaches are any good?
Simple. Just instantiate your entity, set it to an object and pass it to your view in your controller.
Entity
VehicleInfoEntities db = new VehicleInfoEntities();
Stored Procedure
dbo.prcGetMakes()
or
you can add any parameters in your stored procedure inside the brackets ()
dbo.prcGetMakes("BMW")
Controller
public class HomeController : Controller
{
VehicleInfoEntities db = new VehicleInfoEntities();
public ActionResult Index()
{
var makes = db.prcGetMakes(null);
return View(makes);
}
}
PLEASE: If my question isn't clear, please tell me and I'll try to rephrase it
I need [Default Constructor] in LogOnModel, so it can't be removed.
LoadModel+ModelFactory and LogOnModel are physically in different files in different projects AND project2 has reference to project1 and NOT vice versa.
1 - Let say that
type=typeof(LogOnModel). When ObjectFactory.GetInstance(t) is called I want it to call the
parameterized constructor of LogOnModel and pass it the #params
2 - If I'll add to the parameterized constructor of LogOnModel another parameter,for example
public LogOnModel(string param, IPageService pageService)
so ObjectFacytory should call this constructor without any problems
How to configure/initiate ObjectFactory, so this will work?
Thank you
EDITED
//Project1/file1.cs
public void LoadModel(Type type, string param)
{
var factory = new ModelFactory();
var model = factory.Get(type, **param**);
}
public class ModelFactory : IModelFactory
{
public PageModel Get(Type t, **string param**)
{
//NOW I NEED SOMEHOW TO PASS **param** TO EVERY INSTANCE THAT INHERITS FROM **PageModel**
return ObjectFactory.GetInstance(t) as PageModel;
}
}
//Project2/file2.cs
public class LogOnModel : PageModel
{
public LogOnModel()
{
}
public LogOnModel(string param)
{
}
}
public class Model2 : PageModel
{
public LogOnModel()
{
}
public LogOnModel(string param)
{
}
}
public class Model3 : PageModel
{
public LogOnModel()
{
}
public LogOnModel(string param)
{
}
}
StructureMap will use the constructor with the most parameters by default, so that part is easy. Then you just need to configure the value of param like so:
ObjectFactory.Initialize(i => {
i.For<LogOnModel>().Use<LogOnModel>();
});
When you call the container, use the with method to pass in your parameter:
return ObjectFactory.With("param").EqualTo(param).GetInstance(t) as PageModel;