I'm making an application which is similar to a small network.
I have this class :
class Person
{
public string Email {get; set;}
public string Password {get; set;}
public int Age {get; set;}
public long Birthday {get;set;}
... 30 properties more
}
I have this query :
_graphClient.Cypher.Match ("n:Person")
.Where<Person>(n => n.Email == info.Email)
.Return(n => n.As<Person>)
But I want my query ignore the password and return all other properties.
Exactly, I want it to be:
{
Email: "email_1",
Age : 10,
Birthday : 1000
... 30 properties more
}
Can anyone help me please?
Thank you.
There are three options I can think of, but I think only one is really viable for you. You can attach the attribute [JsonIgnore] to your Password property - but this will stop it being serialized ever - and I don't think you want that.
The second option is to use an Anonymous type for your return, so something like:
.Return(n => new {
Email = n.As<Person>().Email,
/* etc */
})
But I think that will mean you'll write a lot of code, which I imagine you'd rather avoid.
The final option is to have something like:
public class Person {
public string Email { get; set; }
/* All other properties, except Password */
}
public class PersonWithPassword : Person {
public string Password { get;set; }
}
Then use Person where you are, and PersonWithPassword where you need the password.
You might find you have a problem if you have a Membership set up to use Person as is - in which case, you'd do something like:
public class PersonWithoutPassword {
public string Email { get; set; }
/* All other properties, except Password */
}
public class Person : PersonWithoutPassword {
public string Password { get;set; }
}
and in your return - you'd return:
Return(n => n.As<PersonWithoutPassword>())
instead.
Related
When I query a table in my database using EF Core 6, i get a IEnumberable or a List of items, like this
public class SqlService
{
private IDbContextFactory<WebContext> CtxFactory { get; set; }
public SqlService(IDbContextFactory<WebContext> dbContextFactory)
{
CtxFactory = dbContextFactory;
}
public List<Test> WithoutMail()
{
using var ctx = CtxFactory.CreateDbContext();
return ctx.Test.Where(p => p.EMail == null).ToList();
}
}
Now my results represent instances of my class "Test" like this:
private class Test
{
public string EMail {get; set;}
public string SomeValue {get; set;}
... more properties
}
What I want is a (not mapped) property, querying the dababase with a value from one of the proerties like:
private class Test
{
public string EMail {get; set;}
public string SomeValue {get; set;}
... more properties
[NotMapped]
public string ValueFromQuery => [CTX].SomeOtherTable.Where(p => p.Value == SomeValue);
}
But of cause, I have no context here and no database service. Is this possbile? Ist this the wrong way? Should I implement another method in SQLService to handle this task?
It would be nice to "extend" the class this way with some additional proerties that come from the db depending on a value in the table.
Consider a simple model class and repository like this:
public class User
{
[Column, Nullable] public string Username { get; set; }
[Column, Nullable] public string Status { get; set; }
[Column, Nullable] public bool Expired { get; set; }
}
public class UserRepository : IUserRepository
{
public IQueryable<User> Get(IDataContext context)
{
using (context)
{
return context.GetTable<User>();
}
}
}
I'd like to add an additional property to the instances of the User class on reads, but this property is not needed on updates or inserts. The desired model would look something like this:
public class User
{
[Column, Nullable] public string Username { get; set; }
[Column, Nullable] public string Status { get; set; }
[Column, Nullable] public bool Expired { get; set; }
public string HostName {get; set;}
}
Essentially I'd like to pass in a hostname value provided by the caller that will travel with the objects. I can do this by using a select statement in my repo class:
using (context)
{
return from user in context.GetTable<User>()
select new User()
{
Username = user.Username,
Status = user.Status,
Expired = user.Expired,
Hostname = hostName
}
}
But this feels wrong, and I'm not sure I want to do this in my repo anyway. Also, many of my POCO classes have a large number of properties and this will be a eyesore. Is there an idiomatic in Linq2DB way to add an arbitrary property to objects retrieved from the DB? Thanks!
You probably can look at OnEntityCreated event of context. Something like that:
context.OnEntityCreated += args =>
{
if (arg.Entity is IHostable hostable)
{
// I see problem here - where to get hostName itself
// because context anyway is not multithreaded, it could
// be a field of current context
hostable.Hostname = context._hostName;
// or
hostable.Hostname = ((IHostProvider)ars.DataContext).HostName;
}
};
I have this maintenance scheduling system, and in im using MVC C# Entity Framework,
I have this table
Truck Table that has - truck id, registration no., kilometer run reading, and i have an JobOrder Table, i want to get the truck id in the truck table so that i can add a JobOrder on a specific Truck i have this JobOrder Controller
public ActionResult AddJobOrder(JobOrderModel jo, int id)
{
var AddJobOrder = db.trucks.FirstOrDefault(s => s.id == id);
var addjo = new joborder()
{
truck_no = AddJobOrder,
description = jo.Description,
worked_performed = jo.worked_performed,
quantity = jo.Quantity,
spare_parts = jo.SpareParts,
run = jo.kilometer_run,
date_finished = jo.DateFinished,
date_started = jo.DateFinished,
};
if (!ModelState.IsValid)
{
db.joborders.Add(addjo);
db.SaveChanges();
return View(jo);
}
return View(jo);
}
I receive the following error:
Error 4 Cannot implicitly convert type 'Pms_system.truck' to 'int'
This is my model
public class JobOrderModel
{
public int truck_no { get; set; }
public DateTime DateStarted { get; set; }
public DateTime DateFinished { get; set; }
public string SpareParts { get; set; }
public int Quantity { get; set; }
public string Description { get; set; }
public int kilometer_run { get; set; }
public string worked_performed { get; set; }
}
Please help me to get the truck id.
It looks like this is just a matter of getting the ID out of the truck - after all, your oddly-named AddJobOrder variable is presumably of type Truck or something similar. I suspect you just need something like:
truck_no = AddJobOrder.id,
After all, that's how you're getting at the truck ID in the query just beforehand. It's not entirely clear why you need the query at all if you only need the truck ID, which has been provided to the method anyway - all you're doing at the moment is allowing you to check whether or not there is such a record, although you should then actually do the check by seeing whether FirstOrDefault returned null.
I would also strongly advise you to take a good look at the names you're using, both in terms of capitalization and semantic names too. (Your AddJobOrder variable should be called truck or something similar by the sounds of it. The fact that it's the same name as the method is doubly confusing!)
Suppose the following situation:
// [Validator(typeof(AddressForSupplierValidator))] <-- Cannot put both
// [Validator(typeof(AddressForCompanyValidator))] <--
// But even if I skip both of them it works great for SERVER SIDE
public class Address
{
public string AddressName { get; set; }
public string StreetName { get; set; }
}
[Validator(typeof(SupplierValidator))]
public class Supplier
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class SupplierValidator: AbstractValidator<Supplier>
{
public SupplierValidator() {
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.Address).SetValidator(new AddressForSupplierValidator());
// AddressForSupplierValidator - Requires AddressName to be .NotEmpty()
}
}
[Validator(typeof(CompanyValidator))]
public class Company
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class CompanyValidator: AbstractValidator<Company>
{
public CompanyValidator() {
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.Address).SetValidator(new AddressForCompanyValidator());
// AddressForCompanyValidator - Requires StreetName to be .NotEmpty()
}
}
As illustrated Address entity is being used by Company and by Supplier.
Now I need to validate Address depending on its context.
The above solution works for SERVER SIDE only. But for CLIENT SIDE:
It doesn't generate data-val- attributes on HTML elements. This is
because it lacks any [Validator(..)] on top Address class
definition. Adding [Validator(..)] solves the data-val- generation
but breaks the ideea of reusing Address entity and validate it
depending on context
Questions:
Why the absence of [Validator()] ontop of Address breaks CLIENT SIDE validaton, even with .SetValidator()?
Why do we need RuleFor(x => x.Address).SetValidator(..); if anyway the validator must be specified on top of the class ?
Some thoughts:
My belief is that specifying .SetValidator(..) for a nested property should be enough. The requirement with adding [Validator()] breaks the ideea of reusing same ViewModel with many validation rules depending on context.
The author already did great job integrating the client validation. And they work if leaving the ideea of reusing the viewmodel.
Temporary solution:
public class AddressBase
{
public string AddressName { get; set;}
public string StreetName { get; set;}
}
[Validator(typeof(AddressForSupplierValidator))]
public class SupplierAddress : AddressBase
{}
[Validator(typeof(AddressForCompanyValidator))]
public class CompanyAddress : AddressBase
{}
It works, but again whats the reason for .SetValidator(new AddressForSupplierValidator()); then !? Kind of redundant.
References:
Related SO question which demonstrates this issue is place at:
Unobtrusive client validation data attributes are not rendered for nested property rules
Is there a way to make a data annotation conditional? I have a table Party where I store both organisations and persons. If I'm adding an organisation I don't want the field surname to be required, but only if I'm adding a person.
public class Party
{
[Required(ErrorMessage = "{0} is missing")]
[DisplayName("Your surname")]
public object surname { get; set; }
[DisplayName("Type")]
public object party_type { get; set; }
...
}
I'd like a condition for the required data annotation of surname, something like:
if (party_type=='P') then surname is required, else the surname can be empty.
EDIT
If I have to move this validation to the controller, how would I do it there? How can I trigger the same error message from there?
You can make your model inherit from IValidatableObject and then put your custom logic into the Validate method. You'll have to remove the RequredAttribute from the property as well. You will have to write some custom javascript to validate this rule on the client as the Validate method doesn't translate into the unobtrusive validation framework. Note I changed your properties to strings to avoid casting.
Also, if you have other validation errors from attributes, those will fire first and prevent the Validate method from being run so you only detect these errors if the attribute-based validation is ok.
public class Party : IValidatableObject
{
[DisplayName("Your surname")]
public string surname { get; set; }
[DisplayName("Type")]
public string party_type { get; set; }
...
public IEnumerable<ValidationResult> Validate( ValidationContext context )
{
if (party_type == "P" && string.IsNullOrWhitespace(surname))
{
yield return new ValidationResult("Surname is required unless the party is for an organization" );
}
}
}
On the client you can do something like:
<script type="text/javascript">
$(function() {
var validator = $('form').validate();
validator.rules('add', {
'surname': {
required: {
depends: function(element) {
return $('[name=party_type]').val() == 'P';
}
},
messages: {
required: 'Surname is required unless the party is for an organization.'
}
}
});
});
</script>
I know this topic has some time, but if you'd like to use only declarative validation for that, you could just use such a simple construction (see this reference for further possibilities):
[RequiredIf(DependentProperty = "party_type", TargetValue = "P")]
public string surname { get; set; }
public string party_type { get; set; }
Update:
Since the ExpressiveAnnotations 2.0, there is a breaking change. Now the same thing can be done in a simpler manner:
[RequiredIf("party_type == 'P'")]
public string surname { get; set; }
In Controller you can check like this:
Before if (ModelState.IsValid)
if (model.party_type == 'p')
{
this.ModelState.Remove("surname");
}