I'm trying to validate model which contains list of ids. There is few simple business rules like 'is it exists, is type is correct' and so on. I wanted to create internal Validator for single item (which is Id) but to avoid asking db for each of entity one by one I'm trying to get all of them and put on dictionary which later I want to pass to internal validators to get concrete entity by id.
RuleForEach(m => m.BunchOfIds)
// how to get it?
.SetValidator(new InternalValidator(_entities));
Any idea? I've tried to create CustomAsync but then I cannot use 'RuleForEach' but for now it looks like only possible option
Related
I want to make a universal method for working with tables. Studied links
Dynamically Instantiate Model object in Entity Framework DB first by passing type as parameter
Dynamically access table in EF Core 2.0
As an example, the ASP.NET CORE controller for one of the SQL tables is shown below. There are many tables. You have to implement such (DEL,ADD,CHANGE) methods for each table :
[Authorize(Roles = "Administrator")]
[HttpPost]
public ActionResult DeleteToDB(string id)
{
webtm_mng_16Context db = new webtm_mng_16Context();
var Obj_item1 = (from o1 in db.IT_bar
where o1.id == int.Parse(id)
select o1).SingleOrDefault();
if ((Obj_item1 != null))
{
db.IT_bar.Remove(Obj_item1);
db.SaveChanges();
}
var Result = "ok";
return Json(Result);
}
I want to get a universal method for all such operations with the ability to change the name of the table dynamically. Ideally, set the table name as a string. I know that this can be done using SQL inserts, but is there really no simple method to implement this in EF CORE
Sorry, but you need to rework your model.
It is possible to do something generic as long as you have one table per type - you can go into the configuration and change the database table. OpenIddict allows that. You can overwrite the constructors of the DbContext and play whatever you want with the object model, and that includes changing table names.
What you can also do is a generic base class taking the classes you deal with as parameters. I have those - taking (a) the db entity type and (b) the api side dto type and then using some generic functions and Automapper to map between them.
But the moment you need to grab the table name dynamically you are in a world of pain. EF standard architecture assumes that an object type is mapped to a database entity. As such, an ID is unique within a table - the whole relational model depends on that. Id 44 has to be unique, for a specific object, not for an object and the table it was at this moment loaded from.
You also miss up significantly on acutally logic, i.e. for delete. I hate to tell you, but while you can implement security on other layers for reading, every single one of my write/update methods are handwritten. Now, it may seem that "Authorize" works - but no, it does not. Or - it does if your application is "Hello world" complex. I run sometimes pages of testing code whether an operation is allowed in a specific business context and this IS specific, whether the user has set an override switch (which may or may not be valid depending on who he is) do bypass certain business rules. All that is anyway specific.
Oh, what you can also do... because you seem to have a lot of tables: do NOT use one class, generate them. Scaffolding is not that complex. I hardly remember when I did generate the last EF core database classes - they nowadays all come out of Entity Developer (tool from Devart), while the db is handled with change scripts (I work db first - i actually want to USE The database and that means filtered indices, triggers, some sp's and views with specific SQL), so migrations do not really work at all.
But now, overwriting the table name dynamically - while keeping the same object in the background - will bite you quite fast. It likely only works for extremely simplistic things - you know, "hello world" example - and breaks apart the moment you actually have logic.
I would like to use AutoMapper to map one collection to another. I know that the convention is to set up a mapping for the child object:
Mapper.CreateMap<User, UserDto>();
And then this works fine:
Mapper.Map<List<UserDto>>(UserRepo.GetAll());
But I'd still like to map the list anyway. For example, I'd like to do something like this:
Mapper.CreateMap<List<User>, List<UserDto>>()
.AfterMap((source, destination) =>
{
// some complex/expensive process here on the entire user list
// such as retrieving data from an external database, etc
}
That way I can still use the first map but also to do something custom with the user list as well. In my scenario, it's looking up event IDs in an external database in another datacenter and I'd like to optimise it by only looking up unique IDs, not doing it object-by-object.
However, when I attempt to map a list of User to a list of UserDto, the mapping just returns an empty list. Putting a breakpoint in the AfterMap function reveals that the destination variable holds an empty list. How can I make AutoMapper do this correctly?
Well, that was embarrassing. Five minutes later, I just figured out that you can add a ConvertUsing function which just proxies to a member-by-member mapping:
Mapper.CreateMap<List<User>, List<UserDto>>()
.ConvertUsing(source =>
{
// some complex/expensive process here on the entire user list
// such as retrieving data from an external database, etc
return source.Select(Mapper.Map<User, UserDto>).ToList());
});
Perhaps that's not how you're meant to do it but it works for me.
I'm working with RavenDB, and I'm trying to do something. I have a base type, Principal, from which two classes are derived: User and ApplicationInstance. In my application, instances of User and ApplicationInstance must be created and stored frequently. The thing is, though, that I need to also be able to query all of the Principal objects stored in the database at once, determine whether a given Principal is a User or an ApplicationInstance, and then query for the entire User or ApplicationInstance object.
How can I do this?
You can define a Multi Map Index that uses as source both the User and ApplicationInstance collections.
If you define your index using C# code (by implementing AbstractMultiMapIndexCreationTask<>), you'll have to call AddMap twice to achieve that (as illustrated in the blog post link above)
If you define the index using Raven Studio, simply click the Add Map button and you'll get a new text area which allows you to define an additional Map.
Note, however, that the output structure of both maps must have the same properties (pretty much as you would do with UNION in SQL).
What are you trying to do? If the end result is to query all Principals, then load the entire User or AppInstance, why not just go straight for querying all Users or all AppInstances?
Raven won't store base classes; it will only store the most derived type (User or AppInstance, in your case). So you'll have a collection of Users and a collection of AppInstances.
If you really need to query both at once, you can use Multi Map indexes. You can also change the entity name and store both in a single Principal collection.
But it's difficult to recommend a solution without knowing what you're trying to do. Explain what you're trying to do and we'll tell you the proper way to get there.
We need to store a list of data we pull from another table that relates to one of our models. (We are too deep into build to add this relationship to our DB where it should be.) When we attempt to load this list in a property of the model that needs it.
We load this list into a dropdown in a view. The error occurs trying to load this list into the model in the controller. The true caveat is that we have a unique dropdown list for each record in our table in the view.
Our Class:
Public class OurModel
public property ID As Integer
Public property First As Integer
Public property Last As Integer
Public property myList As List(Of SelectListItem)//This is our problem member
End class
Controller:
//This ViewModel is what we pass around from page to page to populate the various elements we need that is not tied to a specific model
Public Function LoadList(myViewModel As ViewModel) As Action Result
Using db //our database resource
For i As Integer = 0 to myViewModel.OurModel
//Assume table select statement previously declared and initialized into dbGet
**NOTE: dbGet is retieving data from a different table that is tied to this Model**
dbGet = dbGet.Where(Function(x) x.ID = myViewModel.OurModel.ID)
myViewModel.OurModel.myList = dbGet.ToList().[Select](Function(x) New SelectListItem() With {.Value = x.number, .Text = x.number})//ERROR IS HERE
Next
End Using
End Function
Error:
LINQ to Entities does not recognize the method 'DB.ModelTable get_Item(Int32)' method, and this method cannot be translated into a store expression.
UPDATE: The issue appears to be that LINQ is trying to do something with a the DBContext of a query I do previously in this controller. The error is referencing DB.Employee not DB.Position which is what I am querying.
I have done almost nothing in VB.Net, but it sounds like get_Item(Int32) may be the same as an indexer in C#.
There's a well-known shortcoming that Entity Framework does not support classes that contain an indexer (even if you decorate that property with NotMapped).
I was faced with a similar issue, which was to implement a lockable ObservableCollection. I found that I could not implement IList<T> due to the indexer issue in EF, but that I could implement ICollection<T>.
Lock / Unlock ObservableCollection<T>
If you can replace the semantics of a list with those of a collection, that should solve this problem.
I ended up having to write new classes that connected to the database outside of Entity Framework. If you want to use Entity Framework, make sure you database design is PERFECT before you begin building your application and good luck.
I'm using a custom named query with NHibernate which I want to return a collection of Person objects. The Person object is not mapped with an NHibernate mapping which means I'm getting the following exception:
System.Collections.Generic.KeyNotFoundException:
The given key was not present in the
dictionary.
It's getting thrown when the Session gets created because it can't find the class name when it calls NHibernate.Cfg.Mappings.GetClass(String className). This is all fairly understandable but I was wondering if there was any way to tell NHibernate to use the class even though I haven't got a mapping for it?
Why don't you use:
query.SetResultTransformer(Transformers.AliasToBean(typeof(Person)));
It will insert data from each column in your query into Person object properties using column alias as a property name.
How can you create a query which would return instances of a type that is not mapped ?
I think Michal has a point here, and maybe you should have a look at projections. (At least, this is what I think you're looking for).
You create a query on some mapped type, and then, you can 'project' that query to a 'DTO'.
In order to do this, you'll have to 'import' your Person class, so that it is known to NHibernate, and you'll have to use a ResultTransformer.
Something like this:
ICriteria crit = session.CreateCriteria (typeof(Person));
// set some filter criteria
crit.SetProjection (Projections.ProjectionList()
.Add (Property("Name"), "Name")
.Add (Property( ... )
);
crit.SetResultTransformer(Transformers.AliasToBean(typeof(PersonView));
return crit.List<PersonView>();
But, this still means you'll have to import the class, so that NHibernate knows about it.
By using the class, NHibernate would basically be guessing about everything involved including which table you meant to use for Person, and the field mappings. NHibernate could probably be hacked to do dynamic binding based on matching the names or something, but the whole idea is to create the mappings from plain old data object to the database fields using the xml files.
If there's not a really good reason not to map the class, simply adding the mapping will give you the best results...
That said, you can't use a named query to directly inject results into an unmapped class. You would need to tell it which columns to put into which fields or in other words, a mapping. ;) However, you can return scalar values from a named query and you could take those object arrays and build your collection manually.
To solve this, I ended up using the TupleToPropertyResultTransformer and providing the list of property values. There are a few limitations to this, the main one being that the SQL query must return the results in the same order as you provide your properties to the TupleToPropertyResultTransformer constructor.
Also the property types are inferred so you need to be careful with decimal columns returning only integer values etc. Apart from that using the TupleToPropertyResultTransformer provided a reasonably easy way to use an SQL query to return a collection of objects without explicitly mapping the objects within NHibernate.