I'm using Rethink DB with C# via RthinkDB.Driver https://github.com/bchavez/RethinkDb.Driver.
I know that in relational databases there is a feature to create references in one document to another. In mongodb it is ObjectID, in LiteDB it is BsonRef attribute or Dbref function.
LiteDB example:
public class Order
{
public int OrderId { get; set; }
[BsonRef("customers")] // where "customers" are Customer collection name
public Customer Customer { get; set; }
}
The question is, how i can declare reference of object to another table?
I read this article https://rethinkdb.com/docs/data-modeling/#linking-documents-in-multiple-tables but there are no examples how to insert documents with references.
The c# driver don't expose annotations for your classes. RethinkDB is only storing json documents that can be queried with relations. Consider writting a little ORM, or comment your classes attributes.
Related
I am using code first approach for my .net core project. We are using multiple schemas in single database.
We are maintaining models in different class library projects like Inventory,Sales,Finance etc ..
Model mapping is like ( note : below they are different name spaces)
[Table(name: "Product", Schema = "Inventory")]
public class Product
{
public int ProductId {get;set;}
public string Name {get;set;}
}
[Table(name: "Order", Schema = "Sales")]
public class Order
{
public int OrderId{get;set;}
public int ProductId {get;set;}
public virtual Product Product {get;set;}
}
With in the schema i am able to add relation by using attribute. Now i want to add relation between these tables.
I have tried some tweaks but not working.
Any help is appreciated.
Update:
DBcontext's also different for each schema and they are placed in respective class library
You have conflicting approaches in your current architecture:
On one hand, you have gone for a micro-services approach where each service is dealing with its own bounded context (e.g. Inventory, Sales, etc.). This seems to be confirmed by your use of different database schemas, which can be viewed as logically different databases that happen to be deployed in a single physical database. This is fine, and allows for future scaling / segregation where you might move the inventory data into its own database, for example.
On the other hand, you are trying to treat the datastore as a monolithic artefact where you can build table relationships across the bounded context boundary established by your micro-service approach.
If you wish to maintain your micro-services approach, which is perfectly reasonable, then you have to accept that you cannot rely on database-enforced referential integrity for table relationships that span entities in different micro-services.
You'd need a layer above that can retrieve data from separate micro-services and put them together into entities (preferably DTO entities, not the EF Data Entities used for code-first) that the consumer is looking for.
This layer would first retrieve Orders from the 'Sales' service, and then enumerate your Orders and retrieve the relevant Products from the 'Inventory' service and then map those into DTO entities that include navigation properties between OrderDTO and ProductDTO.
Your Order data entity should not have a virtual navigation property to "Product" but instead just hold a unique id of the Product that the Order relates to (not enforced as a database relationship). Personally, I would go further and introduce a GUID Unique Identifier to the Product data class that can be used in the Order to uniquely identify the product. That way, if you ever do migrate your Inventory tables to a new database, you don't have to worry about managing the Database Identity Column during that migration as the reference 'outside' of the Inventory service to the Product table would be the GUID Unique Identifier.
You have a typo
public virtal Product Product {get;set;}
should be virtual
Also you need a navigation member in Product
[Table(name: "Product", Schema = "Inventory")]
public class Product
{
public int ProductId {get;set;}
public string Name {get;set;}
public virtual ICollection<Order> Orders { get; set; }
}
[Table(name: "Order", Schema = "Sales")]
public class Order
{
public int OrderId{get;set;}
public int ProductId {get;set;}
public virtual Product Product {get;set;}
}
I'm building a mobile app in xamarin that has a lot of relationships between classes. For simplicity consider it to be a "University" app that has the classes: ExamPapers, Students, ExamAnswers.
The ExamPaper class would look like this
public class ExamPapers {
[ManyToMany(typeof(Student_ExamPaper))]
public List<Student> Students { get; set; }
[OneToMany]
public List<ExamAnswers> Files { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<ExamSection> Sections { get; set; }
public string ExamName { get; set; }
[PrimaryKey]
public string Id { get; set; }
}
So at the moment any sqlitenetextension operation (the ones that end with "WithChildren") will interact with all the relationships when I often just want to interact with one at a time. Here are some example scenarios:
A student "Lana" is just granted access to an ExamPaper "Mathematics 101". Now to grant her access I need to load; all other students with access, all the files for the exam, all the sections. Otherwise these relationships get deleted when I call "InsertOrReplaceWithChildren".
I want to find out the first question in an ExamPaper. I call "GetWithChildren(examId)". I now have an object with a lot of information I don't want (e.g. 300 students and 300 ExamAnswers).
Sorry if I missed something relevant in the documentation, but I've read it through a couple times now. https://bitbucket.org/twincoders/sqlite-net-extensions
Thanks.
Answer on your question in title: No. You cannot.
SQLite-Net-Extensions does not provide such flexible API for manipulating related data.
But there is one helpful thing that can be used in specific cases:
You can work with junction tables as simple tables through SQLite-Net methods (methods without *WithChildren postfix) if junction tables has PrimaryKey (Id).
For example if you have any data which you want to get withoud additional (related) data, just simply call Table</*class*/>() method on specific table with Where(/*your condition*/) clause for getting only data that you really need. Then you can save modified data through Update method.
Unfortunately, this thing will not work with relations update (for example, if you want to move one ExamAnswer from ExamPaper to another ExamPaper object) because all SQLite-Net-Extensions attributes inherited from Ignore SQLite-Net attribute which is ignoring in all SQLite-Net operations.
But there is another one workaround (a little hacky), you can specify second class without any SQLite-Net-Extensions attributes and that's provide you to CRUD any field in specific table.
I want to have a page where the user selects from a drop down list the category, then adds a small text about that category and uploads an image where the path of that image is saved in the database rather than the whole image. I have created a table "Categories" where the admin is authorized to fill it and the user only selects from the categories list.
Here is what I have done so far:
The create categories model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace DemoIdentity.Models
{
public class CategoriesAdmin
{
public int ID { get; set; }
[Required(AllowEmptyStrings = false)]
[Display(Name = "category name")]
public string categoryName { get; set; }
}
public class DefaultConnection:DbContext
{
public DbSet<CategoriesAdmin> categories { get; set; }
}
}
Now I want to have another table (Data) which includes (ID, Category (category name selected from table categories), News, Image_Path). This table is in the Default Connection database. The category name is the selected category name from a drop down list, and the image path is an upload image which saves the path rather than the whole image.
I am unsure of how to achieve this.
It appears that you are confusing components of ASP.NET MVC and Entity Framework.
As the Entity Framework site states:
Entity Framework (EF) is an object-relational mapper that enables .NET
developers to work with relational data using domain-specific objects.
It eliminates the need for most of the data-access code that
developers usually need to write.
And the MVC site states that:
The ASP.NET MVC is an open source web application framework that
implements the model–view–controller (MVC) pattern.
The two frameworks meet through your model classes. MVC uses the model class to define the data, logic and rules of the application. In Entity Framework, your model class is mapped to tables in your database where it handles the direct reads and writes for you.
By creating your CategoriesAdmin model class and exposing it as a property in your DbContext class as such:
public class DefaultConnection:DbContext
{
public DbSet<CategoriesAdmin> categories { get; set; }
}
Entity Framework will have mapped your model class to a database table called CategoriesAdmins. If this table does not yet exist in your database, it will automatically create it for you. This approach in Entity Framework is known as Code First to a new Database.
Now since you already have a table that stores the available categories (CategoriesAdmin), you will need to create a second model class (called Data for the sake your example) which contains properties for the other bits of information that you want to store.
public class Data
{
// gets or sets the ID of this Data record.
public int ID {get;set;}
public string ImagePath {get;set;}
// other properties
...
}
Now that you have two model classes, you need to create a relationship between the two. In a SQL database this is achieved by Foreign Keys. In Entity Framework, you can achieve the same by using Navigational Properties.
So we update the Data model class as such:
public class Data
{
// gets or sets the ID of this Data record.
public int ID {get;set;}
public string ImagePath {get;set;}
// gets or sets the ID of the related CategoriesAdmin record.
public int CategoriesAdminId {get;set;}
// gets or sets the related CategoriesAdmin record. Entity Framework will
// automatically populate this property with an object for the related
// CategoriesAdmin record.
[ForeignKey("CategoriesAdminId")]
public virtual CategoriesAdmin CategoriesAdmin {get;set;}
// other properties
...
}
The ForeignKeyAttribute on the CategoriesAdmin property is there to give Entity Framework a further hint of the foreign key column to load the navigational property from.
Finally to be able to use your new Data model class with Entity Framework, you need to add another property to your DbContext class so that you have a means of accessing your data:
public class DefaultConnection:DbContext
{
public DbSet<CategoriesAdmin> Categories { get; set; }
public DbSet<Data> Data { get; set; }
}
Now that you have created your model classes and wired them into Entity Framework, you will now be able to use them in MVC. If you load your Data model into your view (using DefaultConnection.Data), you will be able to access the related CategoriesAdmin record by accessing the CategoriesAdmin property on the Data object.
In short: two tables means you need two models. Both models can be loaded into the single view.
Footnote: Apologies if there are large gaps in my answer as there is a lot to explain that have already been explained in other places far better than what I can. The references I have linked should hopefully fill in the gaps.
Should you need more help, please see all of the tutorials on the ASP.NET MVC website on working with data. They're much better written than my concise attempt. I would recommend following them exactly and getting the examples to work before completing your own project so that you have a better understanding of how the two frameworks work and interact with each other.
I have a quick question about the sqlite-net library which can be found here : https://github.com/praeclarum/sqlite-net.
The thing is I have no idea how collections, and custom objects will be inserted into the database, and how do I convert them back when querying, if needed.
Take this model for example:
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
private string _name; // The name of the subject. i.e "Physics"
private ObservableCollection<Lesson> _lessons;
Preface: I've not used sqlite-net; rather, I spent some time simply reviewing the source code on the github link posted in the question.
From the first page on the sqlite-net github site, there are two bullet points that should help in some high level understanding:
Very simple methods for executing CRUD operations and queries safely (using parameters) and for retrieving the results of those
query in a strongly typed fashion
In other words, sqlite-net will work well with non-complex models; will probably work best with flattened models.
Works with your data model without forcing you to change your classes. (Contains a small reflection-driven ORM layer.)
In other words, sqlite-net will transform/map the result set of the SQL query to your model; again, will probably work best with flattened models.
Looking at the primary source code of SQLite.cs, there is an InsertAll method and a few overloads that will insert a collection.
When querying for data, you should be able to use the Get<T> method and the Table<T> method and there is also an Query<T> method you could take a look at as well. Each should map the results to the type parameter.
Finally, take a look at the examples and tests for a more in-depth look at using the framework.
I've worked quite a bit with SQLite-net in the past few months (including this presentation yesterday)
how collections, and custom objects will be inserted into the database
I think the answer is they won't.
While it is a very capable database and ORM, SQLite-net is targeting lightweight mobile apps. Because of this lightweight focus, the classes used are generally very simple flattened objects like:
public class Course
{
public int CourseId { get; set; }
public string Name { get; set; }
}
public class Lesson
{
public int LessonId { get; set; }
public string Name { get; set; }
public int CourseId { get; set; }
}
If you then need to Join these back together and to handle insertion and deletion of related objects, then that's down to you - the app developer - to handle. There's no auto-tracking of related objects like there is in a larger, more complicated ORM stack.
In practice, I've not found this a problem. I find SQLite-net very useful in my mobile apps.
I need to save and load properties of a Class dynamicly,
but what is the best practis for this ?
I have for now, two classes that I need to save.
public abstract class BaseComponent {
protected int ComponentID { get; set; }
protected string ComponentName { get; set; }
protected Dictionary GetAllProperties{) { /* Reflection */ }
}
public class Article : BaseComponent {
protected string Title { get; set; }
protected string Content { get; set; }
}
Here I'm thinking to table:
Table: Component, ComponentID, Parrent -> and more
Table: ComponentProperties: ComponentID, Key, Value -> and more
I need to use as must of the dotNet framework, but still keep it simpel.
Im think og use a Provider, I need the function og make different data provider:thatcan save to xml file, sql database or oracle database, you name it.
Do I use a provider, or somethnig else ?
The answer for your persistence will depend very much on the scale of what you're writing. Storing XML in files or a database certainly works, as does a metadata driven generic schema (as you described), but making them work for large scale data can be problematic. Salesforce.com did a recent presentation on how they handle dynamic entities in a multi-tenant architecture (see here), but I doubt you need anything of that scale.
My recommendation would be to store as XML to start. The key issues to solve with the generic schema are joins between logical entities and the trouble of pulling together data that belongs to a single entity when it's split out into key/value pairs in a table.
.Net Framework 2.0 or later has a great class that helps you to implement this task, called SettingsBase. You can find it in System.Configuration assembly. You have to create a class for instance BaseComponentSettings and derive it from System.Configuration.SettingsBase. SettingsBase is provider model and you can support many data source as well.