My Domain Classes is as follow:
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; set; }
}
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Author Author { get; set; }
public Blog Blog { get; set; }
}
As you see I have absolutely not any data annotation or attributes for entity framework annotations, and I Configure Entity framework related annotations in another classes for each one using entity framework fluent api.
now I want to replace entity framework with MangoDb.
but in mongo db I needed to place an attribute at list for Id like below:
public class Author
{
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; set; }
}
My Question is is there any way to this configuration outside in another class, and don't touch my poco classes like what we use in entity framework's fluent api.
You can do that by using a BsonClassMap class like:
BsonClassMap.RegisterClassMap<Post>(cm =>
{
cm.MapMember(x => x.Title).SetElementName("_title");
});
The documentatins is here: Mapping Classes
Also there are default conventions, and for Id field you don't need to map it to _id name, it will be handled automatically.
Basically you can use both EntityFramework and MongoDB driver attributes together. But I would not recommend you to use absolutely same data structure that you used in EntityFramework as SQL and NoSQL are completely different approaches. With NoSQL you should think more of how your application is going to consume your data and create your domain, chose optimal embedding strategy and apply indexes accordingly.
You can find some good reading on MongoDB website. Here are some links to start:
http://docs.mongodb.org/manual/core/data-model-design/
http://docs.mongodb.org/manual/core/data-modeling-introduction/
Related
This concerns a c# EF Core 6 CRUD API in a data-first application.
We have a series of tables managed by the API and some separate, related views that give additional user-friendly information concerning the table entries.
An extremely simple example is:
//============================================
public partial class AuditLog : RecordBase
{
public AuditLog()
{
datestampName = "timeOfChange";
isAudited = false;
includeGlobalRecords = false;
}
public long auditLogID { get; set; }
public string tableName { get; set; }
public string primaryKeyValue { get; set; }
public DateTime? timeOfChange { get; set; }
public DateTime timeChangeApplied { get; set; }
public string action { get; set; }
public long? personID { get; set; }
public string ipAddress { get; set; }
public string changesJson { get; set; }
}
public partial class AuditLogList : AuditLog
{
public string personName { get; set; }
}
The original run of "Ef Core Power Tools / Reverse Engineer" created completely separate classes for these, which I then put back to the inherited form I used with nPoco.
The tool also created entries for these in OnModelCreating() like
//=====================
{
...
modelBuilder.Entity<AuditLog>(entity =>
{
entity.HasIndex(e => new { e.timeOfChange, e.tableName, e.primaryKeyValue }, "x1_AuditLog");
entity.HasIndex(e => e.tableName, "x2_AuditLog");
and
modelBuilder.Entity<AuditLogDetailList>(entity =>
{
entity.HasNoKey();
entity.ToView("AuditLogDetailList");
This failed with the message that because the ...List class inherited from the original, it needed to have an active Key. So I removed the HasNoKey().
I then get an error (apparently on another Building pass)
Both 'AuditLogList' and 'AuditLog' are mapped to the table 'AuditLog'.
All the entity types in a hierarchy that don't have a discriminator
must be mapped to different tables. See
https://go.microsoft.com/fwlink/?linkid=2130430 for more information.
Which seems to indicate that EF is forcing the class inheritance onto the database, ignoring the .ToView().
The link describes ways to share fields within tables and links between tables, but not a successful way to dissociate the inheritance from the EF definition.
Is there a way to do this?
I was working on a project on ASP.NET Core where I had to keep track of edits to Contracts here is where I've come so far,
Models -
//Contract Model
public class Contract
{
[Key]
public int Id { get; set; }
public string ContractId { get; set; }
}
//Contrat History Model
public class ContratEditHistory
{
[Key]
public int Id { get; set; }
[DisplayName("Edited By")]
public string EditorId { get; set; }
[ForeignKey("EditorId")]
public virtual ApplicationUser User { get; set; }
public int ContratId { get; set; }
[ForeignKey("ContractId")]
public virtual Contract Contrat { get; set; }
[StringLength(2, MinimumLength = 255)]
public string ChangeReason { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime DateEdited { get; set; }
}
This seems to work fine in logging who made changes to a contract but I want to "store" the previous version of the contract when the contract is updated so users will be able to look up what changes were made. How can I achieve that?
Object versioning can get very complicated. Depending on the complexity of the data you are versioning, and where you are storing it, there may be an easy solution for it. As mentioned in the comments, SQL Server has built-in version tracking for rows in a table. In my experience, these types of solutions work well in some cases, but in general, don't scale well. I would recommend implementing something similar to the "Memento" software pattern for persisting the state of the "Contract" record. In this software pattern, there are three objects, Caretaker, Originator, and Memento.
Caretaker: this would probably be your controller
Originator: this object is responsible for creating and restoring versions of the "contract" entity
Memento: this object saves the state of the contract where ever you want to store it. I would recommend using your existing edit history class and just serialized the contract to JSON and storing it in the table
You would add classes like the following for your application:
//Contrat History Model
public class ContratEditHistory
{
[Key]
public int Id { get; set; }
[DisplayName("Edited By")]
public string EditorId { get; set; }
[ForeignKey("EditorId")]
public virtual ApplicationUser User { get; set; }
public int ContratId { get; set; }
[ForeignKey("ContractId")]
public virtual Contract Contrat { get; set; }
[StringLength(2, MinimumLength = 255)]
public string ChangeReason { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime DateEdited { get; set; }
[Required]
public String SeralizedData { get; set; }
}
//Originator
public class ContractOriginator
{
public ContractEditHistory CreateVersion(string changeReason, ApplicationUser user)
{
// create the ContractEditHistory object and save it
}
public Contract RestoreVersion(ContractEditHistory version)
{
// restore a ContractEditHistory as the current Contract
}
public List<ContractEditHistory> GetVersions(Contract contract)
{
// a helper function to list all the versions for a contract
}
}
As the "Contract" object gets more complex, you may need to expand this out and consider alternative methods of storing the version rather than just serializing it to to a column as in this simple example. Your mileage will vary, good luck! Checkout Wikipedia for more info about this pattern.
https://en.wikipedia.org/wiki/Memento_pattern
I have the following:
public class SomeClass {
public Guid Id { get; set; }
public string Name { get; set; }
// Instead of having
public IEnumerable<Tag> Tags { get; set; }
// I want something like this
public IEnumerable<string> Tags { get; set; }
// more properties here
}
public class Tag {
public Guid Id { get; set; }
public string Name { get; set; }
// I put this here just to show you what I want,
// normally EF Core will generate this for me
public Guid SomeClassId { get; set; }
}
Is it possible to create the above scneario?
I know a good and maybe even better way to do this would be a Many-To-Many Relationship. But it would be neat to just add a new tag to the list and let EF take care of the rest of it.
I know there is Value Conversions, but I can't figure out if it is possible to apply it in this scenario. If I recall correctly you can do something like this in EF 6 with some custom mapping, but I don't see any version to do it in EF-Core.
Thanks in advance.
I have an 'User'class contains two 'Address' properties reference to 'Address' entity, and there is another class - 'Shipment' also associate with 'Address'.
How i can use fluent api on ef core to build a correct relation between entities.
public class Address
{
public int AddressId { get; set; }
public string Street { get; set; }
...
}
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public virtual Address DefaultAddress { get; set; }
public virtual Address BillingAddress { get; set; }
}
public class Shipment
{
public int ShipmentId { get; set; }
public virtual Address DeliveryAddress { get; set; }
}
There is not need to declare explicit configuration, the EF will do everything without any help.
I prepared a working example with and without fluent configuration, you can check it out here. Just switch between commits to see the difference.
As you can notice, there is no differences in generated migration.
I am creating some view models for my ASP MVC web app.
I created "code first" models for database. Is it a good way to derive view models from database models?
Example database model:
public class Project
{
[Key]
public int Id { get; set; }
public int? CustomerId { get; set; }
public int TypeId { get; set; }
public string Number { get; set; }
public string Name { get; set; }
}
View model:
public class ViewModelProject : Project
{
[NotMapped]
public DateTime? Start { get; set; }
[NotMapped]
public DateTime? End { get; set; }
[NotMapped]
public string Manager { get; set; }
}
Is this the right way or is it completely false?
EDIT (subquestion):
I have some very simple database models like ProjectType, which only contains i.e. two properties. Should I also fragment those models in model view or can I make it that way:
Simple database model:
public class ProjectType
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int? Code { get; set; }
}
Can I use it like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public ProjectType Type { get; set; }
}
Or does it have to be fragmented like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public string Type { get; set; }
public int TypeCode { get; set; }
}
I would not recommend doing it this way. I (and many others) have tried it and it doesn't work well. You will inadvertedly run into troubles, since an MVC model has to be tailored to the view and what you get from the DB rarely fits. Sure, you can hammer it into place, but the code quickly gets messy and store-related and UI code starts to mangle together. This even shows in your example, since you have to put the NotMappedAttribute (which is related to data storage), to ViewModelProject (a class at UI level).
There are many other examples to show this problem, but an especially good one I find when you want to serialize a model object to JSON and send it to a JavaScript client. The JSON serializer takes the values of all public properties and adds them to the JSON. If you want to exclude a property, you have to mark it with a ScriptIgnoreAttribute, which you would also have to apply to the base class, which breaks separation between UI and store-related code.
The better way to go is to keep the staorage model and the MVC model separated and to map the data from one to the other (there are already pre-existing frameworks that help you with that, such as Automapper). This comes with additional advantages, for example better testability, since you are now not dependent on a specific data store to create model instances.