How to update or insert an item in RethinkDB? - c#

I am trying to update or insert (if it does not exist) an element in the database but so far I have not found any examples on how to use the Update and Filter provided by the C# Api.(C# Api , not RethinkDB Reql).
Link to api : https://github.com/bchavez/RethinkDb.Driver
Can anyone help me ?
POCO
class Player
{
public long playerId { get; set; }
public long groupId { get; set; }
public int type { get; set; }
public double lat { get; set; }
public double lng { get; set; }
}
class PlayerRequest
{
public Player data { get; set; }
public Auxdata aux { get; set; }
}
This would be the insert request:
dynamic rez = await r.Db(Constants.DB_NAME).Table(Constants.TABLE_CLIENT)
.Insert(playerRequest.data).RunAsync(Con);
I need to perform an update of playerRequest.data based on the playerId or insert the Player if it does not exist.
I have searched the Api but so far no success.
P.S I have tried installing the Linq to ReQL extension, but the methods seam to be unavailable.

After searching and asking the author of the driver which helped me greatly (thank you Brian!) the solution is the following:
In Js we define adhoc objects with {prop1:value1,prop2,value2}
The C# equivalent is using anonymous types: new{prop1:value1,prop2:value2}
r.Db(Constants.DB_NAME).Table(Constants.CLIENT_TABLE)
.Filter(new { playerId = playerRequest.data.playerId })
.Update(new { lng = playerRequest.data.lng, lat = playerRequest.data.lat })
.RunResult<QueryResult>(this.Con);
Also for further explanation you must read this section of the github repository wiki:
https://github.com/bchavez/RethinkDb.Driver/wiki/Extra-C%23-Driver-Features
When in doubt on how to use a method check the Java driver implementation,they are similar (The C# driver extends the Java one)

Related

Conditional Include in asp.net core and Entity Framework

I just started my first project using asp.net core and for the first time I'm gonna use the code repository for my project in C# and VS 2019.
I create a new Model and it called Comment. This Table can save all of the comments on the project, That mean is user comments in POSTS, SOCIALMEDIA, and etc Areas saved in this table
[Key]
public int CommentId { get; set; }
public eTable Table { get; set; }
public int ContentId { get; set; }
[StringLength(1500)]
public string Notes { get; set; }
public virtual AnalysedMarket AnalysedMarket { get; set; }
ContentID is my foreign key, And my eTable enum type is like bellow:
public enum eTable
{
AnalysedMarket,
Blog,
News,
Migration,
}
I created a new class for AnalysedMarket as well to save Users data from our social media area.
[Key]
public int AnalysedMarketId { get; set; }
[StringLength(255)]
public string Images { get; set; }
public int Hits { get; set; }
public string Notes { get; set; }``
Now I created a method in my code repository for extract data using EF and LINQ to get list of AnalysedMarket data but I can't Include my result with Comment table and result of my code repository in the comment section is null always.
public async Task<IEnumerable<AnalysedMarket>> List(int? page, int? perPage, eStatus? status, string userId)
{
var query = _db.AnalysedMarkets.Select(a => a);
if (status.HasValue)
query = query.Where(m => m.Status.Equals(status));
if (!string.IsNullOrEmpty(userId))
query.Where(m => m.CreatedBy.Equals(userId));
query.Include(a => a.Comments.Where(c => c.Table.Equals(eTable.AnalysedMarket) && c.ContentId == a.AnalysedMarketId));
if (page.HasValue && perPage.HasValue)
return await query.OrderBy(a => a.AnalysedMarketId).ToPagedListAsync(page.Value, perPage.Value);
else
return await query.OrderBy(a => a.AnalysedMarketId).ToListAsync();
}
Actually my question is how can I get list of AnalysedMarket data included by Comment data.
And it has a condition and it says include comment if ContentId is equal to AnalysedMarketId and eTable is Table.AnalysedMarket.
I read the articles about conditional Include but I didn't get any thing of them.
Example 1
Example 2
You need to add a reference from AnalysedMarket to comment like this in your AnalysedMarket-Class:
ICollection<Comment> Comments { get; set; }
And then include them while querying your AnalysedMarkets like this:
var query = _db.AnalysedMarkets.Include(c => c.Comments);
/Edit:
Regarding your comment - for this you would need kind of an hierarchy/inheritance structure. It seems to be supported by EfCore and something like this should work:
public class CommentableItem {
ICollection<Comment> Comments {get;set;}
}
public class Comment {
CommentableItem CommentableItem {get;set;}
}
public class AnalysedMarket : CommentableItem {
}
Than you should be able to use the include for each item inheriting from CommentableItem. I did not use the inheritance feature yet (as far as I know this is quite new for EF Core), so for further instructions check the documentation

How do you construct an Entity class to fetch another Entity from repository?

This is a C# Question, using .NET framework built on Asp.NET Boilerplate.
Again, to re-emphasis the question being asked is "HOW...", so if an answer that was provided was a url link or a descriptive explanation on how something was supposed to be done, i would very much appreciate it. (Dont answer questions on how to tie shoelace by showing a picture of a tied shoe, nor do you answer "how to fish" by showing a recording of someone fishing...)
Since the question is pretty basic (i don't need to rephrase/repeat the header again), i'll give an example.
If i have a Forum service, and i create a class to load a Thread. Inside that thread class should be some sort of collection, array, list, or even a dbset of Post that is pulled on construct.
[Table("Thread", Schema = "dbo")]
public class ThreadModel
{
[Key]
public long Id { get; set; }
public string Title { get; set; }
//Idea 1
//Value should automatically be pulled and cached the moment class connects to database
public Post[] Posts { get; set; }
//Idea 2
//Post has a constructor to return all post that matches a thread id. While new tag keeps the return value constantly refreshed.
public Post[] Posts { get { return new Post(this.Id) } }
//Idea 3
//Not sure how collection is supposed to work. Does it automatically just pull or will i need to make a method to request?
public virtual ICollection<Post> Posts { get; set; }
//Example constructor
//When connected to database key-value pairs that match database labels will automatically get stored in class
protected ThreadModel()
{
//Idea 1-A
//Should be a value of null or empty if database yields no results
Posts = new Post();
}
public ThreadModel(int threadid) : this()
{
//Idea 1-A
Id = threadid;
//new Post => returns all posts in db
//Posts default value is all post in db
Posts = Posts.Select(post => post.threadid == this.id)
//Idea 3-A
Posts = Posts.Get(post => post.threadid == this.id)
//Idea 4
Posts = new Posts().GetThread(threadid);
}
}
Side questions
If all entities are created by inheriting Entity then at what point am i exposed to EntityFramework and DbContext?
I love this example here, submitted by a user as they attempt to connect ABP to their database. But their example doesn't show parent/child resources. I'm unable to find the guide they used to create that, and how it relates back to using ABP to fetch EntityFramework's DbContext example
How does this work? I'm unable to find instructions or explanation for this? (What am i to enter into google to get answers on these mechanics?)
[Table("AbpItems")]
public class Item : Entity
{
[ForeignKey("PostId")]
public Post Post { get; set; }
public int PostId { get; set; }
}
How does this integrate into/with abp's EntityFramework?
Where am i supposed to be creating my Database Table/Class? The project follows the Core.csproj, Application.csproj, and EntityFramework.csproj assembly layout. But it seems like every example is creating the classes at different stages or locations of the solution.
use GetAllIncluding. See https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2617
Here's a complete solution ;
namespace EbicogluSoftware.Forum.Threads
{
[Table("Threads")]
public class Thread : FullAuditedEntity
{
[Required]
[StringLength(500)]
public virtual string Title { get; set; }
[Required]
[StringLength(2000)]
public virtual string Text { get; set; }
public virtual List<Post> Posts { get; set; }
public Thread()
{
Posts = new List<Post>();
}
}
[Table("Posts")]
public class Post : FullAuditedEntity
{
[Required]
[StringLength(2000)]
public virtual string Text { get; set; }
}
public class ThreadDto
{
public string Title { get; set; }
public string Text { get; set; }
public List<PostDto> Posts { get; set; }
public ThreadDto()
{
Posts = new List<PostDto>();
}
}
public class PostDto
{
public string Text { get; set; }
}
public class ThreadAppService : IApplicationService
{
private readonly IRepository<Thread> _threadRepository;
public ThreadAppService(IRepository<Thread> threadRepository)
{
_threadRepository = threadRepository;
}
public async Task<List<TenantListDto>> GetThreads()
{
var threads = await _threadRepository.GetAllIncluding(x => x.Posts).ToListAsync();
return threads.MapTo<List<TenantListDto>>();
}
}
}
Where am i supposed to be creating my Database Table/Class?
You can create them in YourProject.Core.proj

$orderBy with duplicate property in odata v4

I have the following models:
public class Field
{
public string Name { get; set; }
public int Order { get; set; }
public int FieldGroupId { get; set; }
}
public class FieldGroup
{
public string Name { get; set; }
public int Order { get; set; }
public virtual ICollection<Field> Field { get; set; }
}
And what I am want to do is a query where I can order first by the group and then by the field, like:
http://localhost:44300/API/odata/IntFieldSet?$count=true&$expand=FieldGroup&$orderby=FieldGroup/Order,Order
However, when I try it I receive the following error:
Duplicate property named 'Order' is not supported in '$orderby'.
Although they have the same name, they are not the same field. If I try order by fields with different names or only one of those per time, it works. Ex:
$orderby=FieldGroup/Order,Name || $orderby=FieldGroup/Order || $orderby=Order
It used to work on odata v3 but not anymore that I am using odata v4.
Anyone have faced this problem before. Can you help me to find out a solution?
Thanks in advance.
I have the same issue using WebAPI OData 5.6 and 5.7.
However they say they fixed it in version WebAPI Odata 5.7: https://github.com/OData/WebApi/issues/376
Will wait for publication of the update.
It is fixed now.
The correct query should look something like:
http://localhost:44300/API/odata/IntFieldSet?$count=true&$expand=FieldGroup&$orderby=FieldGroup/Order asc,Order desc
It will rougly be translate to:
.OrderBy(x => x.FieldGroup.Order).ThenByDescending(x => x.Order);
Here's an example from odata.org:
http://services.odata.org/TripPinRESTierService/Airports?$orderby=Name%20asc,%20Location/Address%20desc

How to map a class properties in dynamodb without using attribute in .net

I am very new in dynamodb. I am following http://www.rkconsulting.com/blog/persistence-model-framework-with-aws-dynamodb
step by step tutorial for connecting and CRUD operation in dynamodb and it`s works fine.
In that tutorial they using attribute mapping for map class properties
[DynamoDBTable("Dinosaur")]
public class Dinosaur
{
[DynamoDBHashKey]
public string Id { get; set; }
[DynamoDBProperty(AttributeName = "Name")]
public string Name { get; set; }
[DynamoDBProperty(AttributeName = "HeightMetres")]
public double HeightMetres { get; set; }
[DynamoDBProperty(AttributeName = "WeightKG")]
public double WeightKg { get; set; }
[DynamoDBProperty(AttributeName = "Age")]
public int Age { get; set; }
[DynamoDBProperty(AttributeName = "Characteristics")]
public List<string> Characteristics { get; set; }
[DynamoDBProperty(AttributeName = "Photo", Converter = typeof(ImageConverter))]
public Image Photo { get; set; }
[DynamoDBIgnore]
public int IgnoreMe { get; set; }
}
My question is there any way to map class properties without using attribute ?
like as mongoDb
public class Employee
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
}
we can write this in this way in a separate class
BsonClassMap.RegisterClassMap<Employee>(cm => {
cm.AutoMap();
cm.IdMemberMap.SetRepresentation(BsonType.ObjectId);
});
Is it possible in dynamodb ?
In the latest version of the .NET SDK you don't have to put in the attribute tags, it will see all read/write properties and upload the attributes as the same name. You would only have to use the [DynamoDBProperty(...)] if you want the attribute name in DynamoDB to be something other than the .NET object name.
So in your case you could simply remove that attribute for all properties except photo (which needs the converter, you could remove the AttributeName part of it) and WeightKg (because the capitalization is different) and you would get the same result.
I see this is a little bit older question now, so it may not have been that way in older versions (not sure) but I'm using 3.3.0.0 of the SDK and it does work that way. You have probably moved on but answering for others that may come upon this thread as I did...
There is no way, the default "strongly typed" client relies on attributes.
If you have time to do the plumbing yourself - there is nothing stopping your from doing your own implementation of the POC to Dynamo mapping though. Amazon client api (AWSSDK.DynamoDBv2) exposes the raw class AmazonDynamoDBClient which handles all the API calls and the DynamoDBConext is just implementation of IDynamoDBContext interface - which exposes all the "strongly typed" operations. So you can make your own implementation and take different mapping approach in it.
Also you can make a feature request for this:
https://github.com/aws/aws-sdk-net/issues

JavaScriptSerializer How to Deserialize an identifier with space

I am having exactly the same problem as described here https://stackoverflow.com/questions/12565464/javascriptserializer-deserialize-an-identifier-with-space but as no one answered thought i'd try again,
API created by someone else in the form of
[{"AdvertId":"1234567","Price Original":"500","Sold":"False"}]
Application already uses a JavascriptSerilalization to populate the named properties on many other API's so do not want to change that really, but my class to hold this data can not have a property with a space in it "Price Original", and this can't be removed or replaced with an _ or something. Are there any methods that can be called to translate the string to something different?
Is there any solution to this or have I got to use JSON.net to deserialize, was some bits on DataContracts I read up on and these might be able to help but I can't seems to find out how to get this to work for my code, and would be nice to know that is possible without investigation this path.
Many thanks in advance
Sample Class
Class Sample
{
public int AdvertId { get; set; }
public string Price Original { get; set; }
public bool Sold { get; set; }
}
You can still use built-in types, but you'll need to use DataContractJsonSerializer instead of JavaScriptSerializer, and add the appropriate DataContract and DataMember attributes - the implementation is a bit different, but still pretty straightforward.
One thing - your Sold property is boolean, but your JSON sample has a string there - booleans are valid JSON types, so you can remove the quotes.
Some working code:
JSON:
[{"AdvertId":"1234567","Price Original":"500","Sold":false}]
C#:
var ser = new DataContractJsonSerializer(typeof(Sample[]));
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(JSON))) {
Sample[] s = (Sample[])ser.ReadObject(ms);
}
[DataContract]
public class Sample {
[DataMember]
public int AdvertId { get; set; }
[DataMember(Name = "Price Original")]
public string PriceOriginal { get; set; }
[DataMember]
public bool Sold { get; set; }
}

Categories