I'd like to fetch data from a database by using Entity Framework into a list, and send it to client (WCF). I want to add all rows from the database to response.Offers.
This part of my code look like that:
private TestEntities bp = new TestEntities();
public TAResponse GetInformation(TARequest request)
{
List<OfferDB> result = bp.OfferDB.ToList();
TAResponse response = new TAResponse();
response.Offers = new List<DataTransferObjects.OfferDto>();
response.Offers.Add(new DataTransferObjects.OfferDto()
{
//???
});
return response; //?result but how?
}
OfferDB is a database imported from SQL Server. Maybe should I use result? But how can I return that?
TAResponse:
[DataContract]
public class TAResponse
{
[DataMember]
public List<OfferDto> Offers { get; set; }
[DataMember]
public OfferDto ThisOffer { get; set; }
}
and simplified TARequest:
[DataContract]
public class TARequest
{
[DataMember]
public int OfferID { get; set; }
[DataMember]
public string KindOfAccommodation { get; set; }
[DataMember]
public string Country { get; set; }
}
You can iterate through your db list and add to DTO list. Effective if you don't have many properties on your Offer object.
List<OfferDB> result = bp.OfferDB.ToList();
TAResponse response = new TAResponse();
response.Offers = new List<DataTransferObjects.OfferDto>();
foreach(OfferDB objCurrentOffer in result)
{
response.Offers.Add(new DataTransferObjects.OfferDto()
{
Prop1 = objCurrentOffer.Prop1,
Prop2 = objCurrentOffer.Prop2
});
}
Alternatively you can use AutoMapper to map EF object to your DTO object. https://github.com/AutoMapper/AutoMapper
Related
Currently, I am using ServiceStack.Aws v5.9.0 to communicate with DynamoDB. I have used PutItem for both creating and updating an item without anticipating data loss in case of concurrency handling.
public class Customer
{
[HashKey]
public int CustomerId { get; set; }
[AutoIncrement]
public int SubId { get; set; }
public string CustomerType { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
...//and hundreds of fields here
}
public class CustomerDynamo
{
private readonly IPocoDynamo db;
//Constructor
public CustomerDynamo()
{
var dynamoClient = new AmazonDynamoDBClient(_region);
var entityType = typeof(Customer);
var tableName = entityType.Name;
entityType.AddAttributes(new AliasAttribute(name: tableName));
db = new PocoDynamo(dynamoClient) { ConsistentRead = true }.RegisterTable(tableType: entityType);
}
public Customer Update(Customer customer)
{
customer.ModifiedDate = DateTime.UtcNow;
db.PutItem(customer);
return customer;
}
}
The above Update method is called in every service/async task that needs to update the data of the customer.
Refer to this article of AWS I decided to implement the Optimistic Locking to save my life from the issue of concurrency requests.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBContext.VersionSupport.html
Assume that the VersionNumber will be the key for Optimistic Locking. So I added the VersionNumber into the Customer model.
public class Customer
{
[HashKey]
public int CustomerId { get; set; }
[AutoIncrement]
public int SubId { get; set; }
public string CustomerType { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
...//and hundreds of fields here
[DynamoDBVersion]
public int? VersionNumber { get; set; }
}
The result is VersionNumber not updated while it should be automatically incremented. I think it is just because the PutItem will override the whole existing item. Is this correct?
I think I need to change from PutItem to UpdateItem in the Update method. The question is how can I generate the expression dynamically to be used with the UpdateItem?
Thanks in advance for any help!
Updates:
Thanks #mythz for the useful information about DynamoDBVersion attribute. Then I tried to remove the DynamoDBVersion and using the UpdateExpression of PocoDynamo as below
public Customer Update(Customer customer)
{
customer.ModifiedDate = DateTime.UtcNow;
var expression = db.UpdateExpression<Customer>(customer.CustomerId).Set(() => customer);
expression.ExpressionAttributeNames = new Dictionary<string, string>()
{
{ "#Version", "VersionNumber" }
};
expression.ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{ ":incr", new AttributeValue { N = "1" } },
{ ":zero", new AttributeValue { N = "0" } }
};
expression.UpdateExpression = "SET #Version = if_not_exists(#Version, :zero) + :incr";
if (customer.VersionNumber.HasValue)
{
expression.Condition(c => c.VersionNumber == customer.VersionNumber);
}
var success = db.UpdateItem(expression);
}
But the changes are not saved except the VersionNumber
The [DynamoDBVersion] is an AWS Object Persistence Model attribute for usage with AWS's DynamoDBContext not for PocoDynamo. i.e. the only [DynamoDB*] attributes PocoDynamo utilizes are [DynamoDBHashKey] and [DynamoDBRangeKey] all other [DynamoDB*] attributes are intended for AWS's Object Persistence Model libraries.
When needed you can access AWS's IAmazonDynamoDB with:
var db = new PocoDynamo(awsDb);
var awsDb = db.DynamoDb;
Here are docs on PocoDynamo's UpdateItem APIs that may be relevant.
I have an application that has two similar but different objects and I want to store those objects in the same collection. What is the best way to do this? And how can I query this collection?
Today my collections is represented by:
public IMongoCollection<Post> Posts
{
get
{
return _database.GetCollection<Post>("posts");
}
}
And I have this class:
public class Post
{
public string Id { get; set; }
public string Message { get; set; }
}
public class NewTypePost
{
public string Id { get; set; }
public string Image { get; set; }
}
So, today I just can save and query using Post class. Now I want to store and retrive the both classes, Post and NewTypePost.
I tried to change the class type from Post to dynamic. But when I did this, I could not query the collections.
MongoDB .NET driver offers few possibilites in such cases:
Polymorphism
You can build a hierarchy of classes and MongoDB driver will be able to determine a type of an object it gets retrieved from the database:
[BsonKnownTypes(typeof(Post), typeof(NewTypePost))]
public abstract class PostBase
{
[BsonId]
public string Id { get; set; }
}
public class Post: PostBase
{
public string Message { get; set; }
}
public class NewTypePost: PostBase
{
public string Image { get; set; }
}
MongoDB driver will create additional field _t in every document which will represent corresponding class.
Single Class
You can still have Post class and use BsonIgnoreIfNull attribute to avoid serialization exception. MongoDB .NET driver will set those properties to null if they don't exist in your database.
public class Post
{
[BsonId]
public string Id { get; set; }
[BsonIgnoreIfNull]
public string Message { get; set; }
[BsonIgnoreIfNull]
public string Image { get; set; }
}
BsonDocument
You can also drop strongly-typed approach and use BsonDocument class which is dynamic dictionary-like structure that represents your Mongo documents
var collection = db.GetCollection<BsonDocument>("posts");
More details here
dynamic
Specifying dynamic as generic parameter of ICollection you should get a list of ExpandoObject that will hold all the values you have in your database.
var collection = db.GetCollection<dynamic>("posts");
var data = collection.Find(Builders<dynamic>.Filter.Empty).ToList();
var firstMessage = data[0].Message; // dynamically typed code
Suppose I have the next conn to a test database:
var mongoClient = new MongoClient(new MongoClientSettings
{
Server = new MongoServerAddress("localhost"),
});
var database = mongoClient.GetDatabase("TestDb");
Then I can do something like:
var col = database.GetCollection<Post>("posts");
var col2 = database.GetCollection<NewTypePost>("posts");
To get two different instances of IMongoCollection but pointing to the same collection in the database. Further I am able to save to each collection in the usual way:
col.InsertOne(new Post { Message = "m1" });
col2.InsertOne(new NewTypePost { Image = "im1" });
Then, I'm also able to query from those collection base on the specific fields:
var p1= col.Find(Builders<Post>.Filter.Eq(x=>x.Message, "m1")).FirstOrDefault();
var p2 =col2.Find(Builders<NewTypePost>.Filter.Eq(x=>x.Image, "im1")).FirstOrDefault();
Console.WriteLine(p1?.Message); // m1
Console.WriteLine(p2?.Image); // im1
I don't know if that's what you want but it uses the same collection. BTW, change the Id properties to be decorated with [BsonId, BsonRepresentation(BsonType.ObjectId)]. Hope it helps.
Use the BsonDocument data type. It can do all of that. BsonDocument and dynamic back and forth is very convenient.
public class CustomObject{
public long Id{get;set;}
public string Name{get;set;}
public List<(string,object)> CollectionDynamic{get;set;}
}
// inserted in mongo
//public class CustomObject_in_Db{
// public long Id {get;set;}
// public string Name {get;set;}
// public string field2 {get;set;}
// public string field3 {get;set;}
// public string field4 {get;set;}
// public string field5 {get;set;}
// }
// something code... mapper(config)
Automapper.Mapper.CreateMap<BsonDocument,CustomObject>()
.ForMember(dest=>dest.Id, a=>a.MapFrom(s=>s.Id.GetValue(nameof(CustomObject.Id)).AsInt64)
.ForMember(dest=>dest.Name, a=>a.MapFrom(s=>s.Id.GetValue(nameof(CustomObject.Name)).AsString)
.ForMember(dest=>dest.CollectionDynamic, a=>a.MapFrom(s=>_getList(s));
// .......
private List<(string, object)> _getList(BsonDocument source){
return source.Elements.Where(e=>!typeof(CustomObject).GetProperties().Select(s=>s.Name).Any(a=>a ==e.Name)).Select(e=>e.Name, BsonTryMapper.MapToDotNetValue(e.Value)));
}
I don't know how to convert LINQ query to List type of Owner with data from Transport table and pass it to WPF form (using MVVM)
DB structure :
Owner has many cars, so I described relation like this:
public partial class Transport
{
public Transport()
{
TransportOwners = new List<TransportOwner>();
}
[Key]
public int TransportID { get; set; }
public string PlateNo { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public virtual ICollection<TransportOwner> TransportOwners { get; set; }
}
public partial class Owner
{
[Key]
public int OwnerID { get; set; }
public int TransportID { get; set; }
[ForeignKey("TransportID")]
public virtual Transport Transport { get; set; }
[NotMapped]
public string PlateNo { get; set; }
[NotMapped]
public string Brand { get; set; }
[NotMapped]
public string Model { get; set; }
}
In ViewModel I created list type of Owner :
private List<Owner> _haveList;
public List<Owner> HaveList
{
get { return _haveList; }
set
{
if (value != _haveList)
{
_haveList = value;
RaisePropertiesChanged("HaveList");
}
}
}
Now I am trying to get the data :
using (var dbContext = new DataModelContext())
{
var query = dbContext.Owners.AsQueryable();
query = query.Where(o => o.OwnerId.Equal(OwnerParameter));
query = query.Select(t => new
{
Model = t.Transport.Model,
Brand = t.Transport.Brand,
PlateNo = t.Transport.PlateNo
}).ToList();
// Here I see data I need (list of Transport by Owner)
HaveList = query;
'System.Collections.Generic.List<<anonymous type: ... >>' to 'System.Collections.Generic.List<DataModels.Owner>'
In Linq-to-Entities you can only project to an anonymous type or a regular class. You can't project to an existing entity type
var result = (from o in query
where o.OwnerID==OwnerParameter
select new OwnerModel
{
Model=o.Transport.Model,
Brand=o.Transport.Brand
}).ToList();
1 - You should try to use a named object
HaveList= query.Select(t => new OwnerModel
{
Model = t.Transport.Model,
Brand = t.Transport.Brand,
PlateNo = t.Transport.PlateNo
}).ToList();
2 - Your query object is created as IQuerible, then you try to assign it as a List
query = query should not work I think.
Note that OwnerModel should fire INotificationEvent when one of the property is modified :)
private List<OwnerModel> _haveList;
public List<OwnerModel> HaveList
{
get { return _haveList; }
set
{
if (value != _haveList)
{
_haveList = value;
RaisePropertiesChanged("HaveList");
}
}
}
Finally I have what I need, thank You for Your help
List<Owner> list = DBContext.Owners.Where(to => to.OwnerID == ownerParameter).ToList();
HaveList = list.Select(t => new Owner()
{
Model = t.Transport.Model,
Brand = t.Transport.Brand,
PlateNo = t.Transport.PlateNo
}).ToList();
I have obtained the list of data from database in the following way
List<MakerCheckerModel> mkckdata = new List<MakerCheckerModel>();
var dataContext = new PetaPoco.Database("MessageEntity");
mkckdata = dataContext.Query<MakerCheckerModel>(PetaPoco.Sql.Builder.Append("Select * from MakerChecker1")).ToList();
The data comes in mkckdata. My model is of the following way.
public class MakerCheckerModel
{
public int MakerCheckerId { get; set; }
public string OldJson { get; set; }
public string NewJson { get; set; }
public string ModelName { get; set; }
}
Now I want to put the value obtained in OldJson and NewJson of mkckdata in new List type of model variables so that I can manipulate it further.I want something like this.
List<MakerCheckerModel> oldDataList = new List<MakerCheckerModel>();
oldDataList.Add(mkckdata.OldJson));
But this is not allowed here. PLease help me how to do this.
Probably the questin title is not self-explanationary.
I have an ASP.NET MVC5 project with Entity Framework 6. I use code first and I've implemented a TPH pattern for an entity.
There's a base Request entity (I've removed most fields, it's just an example).
public class Request
{
public int Id { get; set; }
public string Title { get; set; }
}
also there's some models with exclusive properties that extend it:
public class RequestQuestion : Request
{
public string Question { get; set; }
public string Answer { get; set; }
}
public class RequestForWork : Request
{
public string WorkName { get; set; }
}
Each of them is added to the EntityContext:
public DbSet<Request> Requests { get; set; }
public DbSet<RequestQuestion> RequestQuestions { get; set; }
public DbSet<RequestForWork> RequestForWorks { get; set; }
When I create some of the requests I add them like this:
var db = new EntityContext();
var requestQuestion = new RequestQuestion{ some initialization };
this.db.Requests.Add(requestQuestion);
this.db.SaveChanges();
And here comes the question. When I query requests of the user
var requests = this.db.Students.Find(userId).Requests.ToList();
in debug I can access the properties of the extending class for every request through the base. So, is there a way to somehow get a type of class that is extending the selected entity and to access it's properties?
Currently to build a list of all requests and fill some viewmodel with data I need to seperately select every type of request and fill a global list from these seperate selects.
You need to cast the base type to its subtype and test for null
foreach (r in requests)
{
var rq = r as RequestQuestion;
if(rq != null)
{
string rq = rq.Question
}
var rfw = r as RequestForWork;
if(rfw != null)
{
string wn = rfw.WorkName;
}
}