(C#) What is an entity? - c#

I try to read C# ECMA to find out what an entity is but failed.
Is this a instance of class?
Or types+members?
Or any single word in the code that shows no red wavy line under it?

Entity is a semantic i.e. relating to meaning in language or logic. An entity is something that exists in itself, actually or potentially, concretely or abstractly, physically or not. It needs not be of material existence.
An entity usually refers to something, anything really, that has a unique and separate existence.
In software development this word is almost only used to denote that one instance is different from another instance and they are independent of each other.
A class, on the other hand, defines or contains the definition of an object. Once that object is constructed based on the definition, then you get your instance or object instance.
Hope it helps ;)

In C# term entity is commonly related to database representation of the table and should contain an Id attribute.

Generally, an entity is a unit of existence, an existing or real thing. Something that can have properties ascribed to it that distinguishes it from another unit with similar characteristics.
I have a table and you have a table. If I describe my table in enough detail then at some point it will be possible to distinguish my table from yours.
In object-oriented programming an entity corresponds to an object instance. In data modelling it corresponds to a unit of data rather than something necessarily having a physical presence.

I think they are using it in it's broadest meaning
Entity: something having real or distinct existence; a thing, esp when considered as independent of other things
So an Entity can be instance of class and types+members
Depending on the context.
Lets say you are talking about class definitions if two classes can be "considered as independent"(having different namespaces) they will call it an Entity.
If you are talking about some sort of business logic you might use the "Entity" word for all objects that have the same Id value stored in the in memory property or Database.
Essentially if you can have a function areTheSame(x,y)=>[true,false] and the result of the function for all posible x and y can be false you can call that x or y an entity.

An entity in a broader setting is just a "something" that exists.
In the C# ECMA an entity is a placeholder for something that you refer to.
This could be a an instance if you refer to an entity created from a class. Or for example the following section defined a scope the following way:
The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name.
So to acces a given something (an entity), you need to reference the scope to refer to it. This could be a class, an instance, a static method or else.

Practically speaking and within the realm of CRUD web applications, an entity is simply a class representation of a database table.
Suppose you have a web application consisting of a database with three tables, each having a number of attributes:
Table 1: User
Name
Surname
ID_Number
Table 2: Address
Residential_address
Postal address
Table 3: Preferences
Food
Color
If you wanted to use this database within your web application, you would need to create three entities which look like this.
public class User
{
public string Name { get; set; }
public string Surname { get; set; }
public string IDNumber { get; set; }
}
public class Address
{
public string ResidentialAddress{ get; set; }
public string PostalAddress{ get; set; }
}
public class Preferences
{
public string Food{ get; set; }
public string Color{ get; set; }
}
In a large number of C# web projects, if you deal with databases, your project would likely have a folder called "entities" and it would include classes called entities, just like the examples shown above.
There is quite a bit of qualifying required on the above and it also strongly depends on what framework you use, but the above is the most common practical interpretation on entity.

Related

How do I use the UserManager from project A in project B?

Both project A and project B are ASP NET Core 2.2 apps.
Project B uses Hangfire for background jobs and does very little else, and the fact that it uses Hangfire may not even be important (more on this at the bottom). Project A enqueues jobs on B's Hangfire.
Now, let's say I have my class representing a task, called Job. This is contained in project C, a plain old class library referenced by project B, and which in turns references other projects containing the entities it's working with.
Dependencies are to be injected into this class through the constructor:
public class Job
{
public Job(UserManager<ApplicationUser> userManager,
IThisRepository thisRepository,
IThatRepository thatRepository)
{
}
public void Execute(string userId)
{
// this is where the work gets done
}
}
and for the most part they do get injected: IThisRepository and IThatRepository are injected and they work... mostly.
In project B's Startup.cs, the one that is supposed to run this job, I manually and successfully registered those interfaces, along with the DbContext that they require a some other stuff.
UserManager was quite a bit harder to register manually because of all the parameters its constructor requires, so since I didn't really need it inside my job, I just decided to make a few changes.
Now, an example of the entities I'm working with is as follows:
public class Category
{
[Key]
public int Id { get; set; }
// several other properties of primitive types
public ApplicationUser User { get; set; }
[Required]
public string UserId { get; set; }
}
public class Dish
{
[Key]
public int Id { get; set; }
// several other properties of primitive types
public ApplicationUser User { get; set; }
[Required]
public string UserId { get; set; }
public Category Category { get; set; }
[Required]
public string CategoryId { get; set; }
}
now the problem is this: inside of Job I try to create a new Dish and associate it with both the user and the category. Since I just have the user id and I don't have access to UserManager, this is what I try to do:
// ...
var category = await categoryRepository.FindByUserAndCode(userId, "ABC");
// this is a category that is guaranteed to exist
var dish = new Dish();
dish.UserId = userId;
// notice there's no dish.User assignment, because I don't have an ApplicationUser object
dish.Category = category;
dishRepository.Upsert(dish); (which internally either creates a new entity or updates the existing one as appropriate)
and this is where it all breaks down, because it says that a category with the same Id I'm trying to insert is already present, so I'm trying to duplicate a primary key.
Since the category with code ABC for this user exists in the db, I thought it was odd.
Here's the thing: the instance of Category that the repository returns does have it's UserId property populated, but the User property is null.
I think this is what causes my problem: EF probably sees that the property is null and considers this object a new one.
I don't know why it comes up null (and it does even for other entities that all have a property referencing the user), but I tried to backtrack and, instead of using just the user id, I wanted to try to get Hangfire to instantiate Job injecting UserManager<ApplicationUser> into it, so at least I could get an instance of my user by its id.
It's worth noting that this works in other parts of project A, it's just that when I'm executing the background job something goes horribly wrong and I can't for the life of me figure out what it is.
However the dependencies of UserManager are many, and I fear I might be barking up the wrong tree or doing it completely wrong.
I said that the fact I'm using Hangfire might not matter because the assumption under which it operates is: just give me the name of your class, I'll take care of instantiating it as long as all the dependencies have been registered.
Anyone has done this before and can help shed some light?
You've included an absolute ton of information here that is entirely inconsequential to the problem at hand. What your issue boils down is simply the exception you're getting when attempting to add a dish: "a category with the same Id I'm trying to insert is already present, so I'm trying to duplicate a primary key."
This is most normally caused by attempting to use a detached entity as a relationship, i.e.:
dish.Category = category;
If category is detached from the context, then EF will attempt to create it because of this assignment, and since it already exists, that creation fails. We can't see what's going on in categoryRepository.FindByUserAndCode, but I'd imagine you're either calling AsNoTracking with the query, or are newing up an instance of Category manually yourself. In either case, that instance, then, is detached from the context. To attach it again, you simply need to do:
context.Attach(category);
However, you don't have direct access to your context here. This is yet one more reason that you should never use the repository pattern with EF. So much pain and suffering has been subjected on developers throughout the year by either bad advice or erroneously attempting to do things as they are used to.
EF is an ORM (object relational mapper), which is a fancy way of saying that it is itself a data layer. The DbContext is the unit of work and each DbSet is a repository... already. The repository pattern is for abstracting low-level database access (i.e. all the crud of constructing SQL strings, for example). EF is already a high-level abstraction, trying to cram it into another repository pattern layer only cripples it and leads to problems like what you're experiencing here.
Long and short, the issue is that category is detached. You need to either ensure that it never becomes detached in the first place (i.e. don't use AsNoTracking for example) or find a way to ensure that it's reattached later. However, your best bet here is to throw away all this repository garbage completely and just use the context directly. Choosing to use an ORM like EF is simply choosing to use a third-party DAL, rather than write your own. Writing your own, anyways, on top of that is just wrong. You use the built in routing framework in ASP.NET Core. You use the built in templating engine (i.e. Razor). Do you feel the need to put some abstraction around those? Of course not, so why is a DAL any different? If you simply must create an abstraction, then use a meaningful one such as CQRS, service layer, or microservices patterns.

SqliteNetExtensions is it possible to ignore a specified child when calling InsertOrReplaceWithChildren()?

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.

DDD - POCOs. First step

It is my first time in DDD. In company we don't have "domain master". I have only read about DDD I need to implement domain with DDD aproach.
So, I know that in domain there are no place for Database features. But if I would use my domain with Entity Framework and NOSQL database. With EF i need to make collections virtual and in constructor alloce as new. This is bad in DDD?
My code:
public abstract class Merchant : AggregateRoot
{
public Company Company { get; set; } // Entity
public string CIF { get; set; }
public string NIP { get; set; }
public string Status { get; set; }
public Address Address { get; set; } // Entity
public Group Group { get; set; } // Entity
public virtual ICollection<Brand> Brands { get; set; } // Brand is entity
protected Merchant()
{
this.Brands = new List<Brand>();
}
}
There are multiple shades of opinion about that issue in the DDD space.
To me, the primary measure of "persistence ignorance" is :
Will a change in my database break things in my domain layer, forcing
me to open up the domain model and modify stuff to fix it ?
If we look at your example, the answer is clearly no.
It would have been the case if you had for example data annotations in your entity class referring to table or column names, or if you relied on mapping by convention and changed the Merchant table name to Reseller in the DB. But having a default constructor and virtual property doesn't make your domain class more fragile in the face of database changes.
Then you have a secondary question, a less critical one IMO :
Is the ORM a hindrance in my implementing domain entities just the way I
want and as DDD-compliant as they need to be ?
This one is a bit more challenged. It might be, if the ORM forces you to add operations that can leave the domain object in an inconsistent state. I wouldn't consider a parameterless constructor as prone to that though, since it can be private and thus impossible to shoot yourself in the foot with. Same with setters.
Some consider that small traces such as the need for virtual and parameterless constructor violate DDD, because your entities are not pure any more, they contain oddities caused by the presence of an ORM. Therefore, you should create a second "persistence" model to leave the domain model untainted. I don't. I think most of the time it's not worth the tradeoff in terms of complexity - you can live with the small quirks as long as the first rule of persistence ignorance holds.
I would be more concerned about having public setters than a protected default constructor or a virtual property. The problem with that is can lead to an inconsistent state of the entity. For example, you may want to validate the address properties to make sure all the required properties are set and the postal code corresponds to the state/country. Another example would be status transitions; once the entity reaches a "final" status, it cannot be changed anymore.
While you can create separate validators for entities and use them before you persist the entities, it defeats the purpose of a rich domain model.
There are a few ways to get around it. You can create DTO objects that mirror the database schema and use hydrators to populate the entities (with protected/internal property setters) from those DTOs assuming the data in the database is always in the consistent state. All the new changes will have to go through entity methods to get validated. Then you would hydrate the DTOs based on the latest entity data and persist it.
CQRS with event sourcing is a more advanced alternative of this that persists all changes as an immutable log/event-store rather than (only) the latest data snapshot. But that is not something that is necessary for every domain scenario.

Using interfaces in LINQ database queries

I am working on part of an application that simply pulls information from the database and displays it to users. For simplicity sake, let us assume I have a database with two tables, Cats and Dogs. Both tables have manually assigned primary keys and are never duplicated/overlapped. The goal I am trying to achieve is to perform 1 LINQ query that will concat both tables.
I recently asked this question regarding performing a LINQ concat on two collections of objects, Cats and Dogs, that were manually created in code. I advise reading the previous question as it will give much insight to this one.
The reason I wish to use interfaces is to simplify my queries. I currently have a solution that .Select each of the columns I need into an anonymous type. This would work fine for this instance, but will consume pages with the data I am working with.
The different between that previous question and this one is that I am trying to pull these animals from a database. From my analysis, it seems that .NET or Entity Framework is not able to relate my database to my interface
Model (From old question)
public interface iAnimal
{
string name { get; set; }
int age { get; set; }
}
public class Dog :iAnimal
{
public string name { get; set; }
public int age { get; set; }
}
public class Cat:iAnimal
{
public string name { get; set; }
public int age { get; set; }
}
Here are some different LINQ queries I have tried and the resulting error. The first example will be using the solution from the previous question.
var model = _db.Cats.Concat<iAnimal>(_db.Dogs).Take(4);
System.ArgumentException: DbUnionAllExpression requires arguments with compatible collection ResultTypes.
Without Covariance:
var model = _db.Cats.Cast<iAnimal>().Concat(_db.Dogs.Cast<iAnimal>());
System.NotSupportedException: Unable to cast the type 'Test.Models.Cat' to type 'Test.Interfaces.iAnimals'. LINQ to Entities only supports casting Entity Data Model primitive types.
From the above error, it looks like I am not able to use interfaces to interact with databases as it is not mapped to any particular table.
Any insight would be much appreciated. Thanks
EDIT
In response to #Reed Copsey, with your solution, I get the same error as my example without covariance. I tried changing the view's type to match what the error recommends, which results in this error
System.InvalidOperationException: The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery`1[Test.Interfaces.iAnimal]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Test.Models.Cat]'.
You database knows nothing about your interface and you will probably not be able to get this working. I see two options.
You could use inheritance - for example supported by the Entity Framework - and inherit both entities from a common base entity. Than you will be able to perform queries against the base type but this may require changes to your data model depending on the way you implement inheritance at the database level.
Have a look at the documentation for TPT inheritance and TPH inheritance. There are still other inheritance models like TPC inheritance but they currently lack designer support.
The second option is to fetch results from both tables into memory and use LINQ to Objects to merge them into a single collection.
var dogs = database.Dogs.Take(4).ToList();
var cats = database.Cats.Take(4).ToList();
var pets = dogs.Cast<IPet>().Concat(cats).ToList();
Also note that your query
var model = _db.Cats.Concat<iAnimal>(_db.Dogs).Take(4);
seems not really well designed - the result will definitely depend on the database used but I would not be surprised if you usually just get the first four cats and never see any dog.

EF4 exception with relationship

I have two entities and there are their POCO:
public class DocumentColumn
{
public virtual long Id { get; set; }
public virtual string Name { get; set; }
public virtual long? DocumentTypeId { get; set; }
}
public class DocumentType {
public virtual long Id { get; set; }
public virtual string Name { get; set; }
}
There is a relation between those two entities. In the db the relation called:FK_T_DOCUMENT_COLUMN_T_DOCUMENT_TYPE.
When I do:
DocumentColumns.Where(x => x.DocumentTypeId == documentTypeId).ToList();
I get the exception:
{"Metadata information for the relationship 'MyModel.FK_T_DOCUMENT_COLUMN_T_DOCUMENT_TYPE' could not be retrieved. If mapping attributes are used, make sure that the EdmRelationshipAttribute for the relationship has been defined in the assembly. When using convention-based mapping, metadata information for relationships between detached entities cannot be determined.\r\nParameter name: relationshipName"}
I tryed to remove the relationship and the DocumentColumn table and reload them but the code still throws the exception.
Whet does this exception means and how can I solve it?
EDIT:
The exception happens also If I do DocumentColumns.ToList();
(Presuming you are talking about Code First ....)
There is no information in either class to let CF know that there is a relationship between them. It doesn't matter that the database has the info. Entity Framework needs to have a clue about the relationship. You provide only a property with an integer. CF cannot infer a relationship. You must have something in one class or another that provides type or another. This is not a database. It's a data model. Very different things.
But that's not all. I'm guessing that this is a one to many relationship. You could either put a List property into the Document class or a Document property in the DocumentColumn class. If you only do the latter, CF and EF will NOT know about the 1:. It will presume a 1:1 (that is if you leave DocumentId integer in there, otherwise it will presume a 1:0..1). However, I think you could get away with this and then just configure the multiplicity (1:) in fluent API.
UPDATE...reading your question again, I think you are using an EDMX and designer not code first. What are you using to create your POCO classes? Are you doing code gen from the EDMX or just writing the classes. I still think the lack of a navigation property in at least ONE of the types might be the cause of the problem. The ERROR message does not suggest that...I'm only coming to this conclusion by looking at the classes and inferring my understanding of how EF works with the metadata. I could be barking up the wrong tree. FWIW, I have asked the team if they are familiar with this exception and can provide some idea of what pattern would create it. It's pretty bizarre. :)
It seems odd to me that you are using EF with a defined relationship and you are not using the related property. Can you not do:
DocumentColumns.Where(x=>x.DocumentType.Id == documentTypeId).ToList();
This is what I would expect to see in this instance.

Categories

Resources