How to change the value based getting value in Entity Framework - wpf

I have taken the values from database using Entity Framework , I have that a class called EmployeeDetail in that I have one property called JOined AS.
It gives the values as 'F' for fresher and 'E' for experience.. I need to display this value in
DataGrid as Experience or Fresher instead of F or E..
For that I have created the partial class for EmployeeDetail and created one property CustJoinedAs ...
But I didn't get idea to compare the value and return the required value to DataGrid Column...
Here I also have to give each value to DataGrid.. is it automatically bind when I give the property to Column in DataGrid...or any propetyChanged Events have to be Write..
please give a brief idea.. and Code..
Thank you

You can implement the property in partial class like
public partial class EmployeeDetail
{
public string CustJoinedAs
{
get{return this.JoinedAs = "E"? "Experienced" : "Fresh";}
}
}
And bind column of grid to CustJonedAs despite of JoinedAs.

Related

Not Nullable fields in SQL Server Still Considered Required Fields in ASP.NET MVC

I have a non nullable fields in a table with default values set already in the property "Default Value or Binding" in SSMS. I linked this table in an ASP.Net mvc application. When I created the view and when running the create view, it still asking me to enter the required fields for the non nullable fields even though i assigned a default value for them.
After this I removed the line:
#Html.ValidationMessageFor(model => model.position, "", new { #class = "text-danger" })
which is bellow each
#Html.EditorFor statement, but this time it post me back to the same page with no changes in the database.
How can I get rid of the message in the required fields as I have already default value for them?
Simply you can create a constructor in your model. It will initialize default values once new instance is created. If user provides that fields, then it will be overridden. If no, value from constructor will be passed to EF.
What you are trying to do now, won't work according to specifications: https://msdn.microsoft.com/en-us/library/ms187872.aspx
Here you can see how to achieve what you want, considering that this field will always be generate in database.
This is one of the many reasons not to use entity models as viewmodels. MVC doesn't care that the required field has a default value, that information is database-related and not related to input validation.
Introduce a viewmodel where those properties are not required, and map the posted viewmodel to your entity model.
So, given an entity model that looks like this:
public class SomeEntity
{
// this property is not-nullable in the database
[Required]
public string SomeRequiredDatabaseField { get; set; }
}
Because the SomeRequiredDatabaseField is NOT NULL, it is annotated as such by Entity Framework, even if it has a default value. MVC will pick up this annotation, and consider the model not valid when the property has no value.
Now if you introduce a viewmodel, you can tell MVC that this property is not required:
public class SomeViewModel
{
// Not required
public string SomeRequiredDatabaseField { get; set; }
}
Now in your controller, you map the viewmodel to the entity model (preferably using AutoMapper):
public ActionResult Post(SomeViewModel model)
{
if (ModelState.IsValid)
{
var entityToSave = new SomeEntity
{
SomeRequiredDatabaseField = model.SomeRequiredDatabaseField
};
db.SomeEntity.Add(entityToSave);
}
// ...
}

Dapper can't ignore nested objects for parameter?

I am beginning to use Dapper and love it so far. However as i venture further into complexity, i have ran into a big issue with it. The fact that you can pass an entire custom object as a parameter is great. However, when i add another custom object a a property, it no longer works as it tries to map the object as a SQL parameter. Is there any way to have it ignore custom objects that are properties of the main object being passed thru? Example below
public class CarMaker
{
public string Name { get; set; }
public Car Mycar { get; set; }
}
propery Name maps fine but property MyCar fails because it is a custom object. I will have to restructure my entire project if Dapper can't handle this which...well blows haha
Dapper extensions has a way to create custom maps, which allows you to ignore properties:
public class MyModelMapper : ClassMapper<MyModel>
{
public MyModelMapper()
{
//use a custom schema
Schema("not_dbo_schema");
//have a custom primary key
Map(x => x.ThePrimaryKey).Key(KeyType.Assigned);
//Use a different name property from database column
Map(x=> x.Foo).Column("Bar");
//Ignore this property entirely
Map(x=> x.SecretDataMan).Ignore();
//optional, map all other columns
AutoMap();
}
}
Here is a link
There is a much simpler solution to this problem.
If the property MyCar is not in the database, and it is probably not, then simple remove the {get;set;} and the "property" becomes a field and is automatically ignored by DapperExtensions. If you are actually storing this information in a database and it is a multi-valued property that is not serialized into a JSON or similar format, I think you are probably asking for complexity that you don't want. There is no sql equivalent of the object "Car", and the properties in your model must map to something that sql recognizes.
UPDATE:
If "Car" is part of a table in your database, then you can read it into the CarMaker object using Dapper's QueryMultiple.
I use it in this fashion:
dynamic reader = dbConnection.QueryMultiple("Request_s", param: new { id = id }, commandType: CommandType.StoredProcedure);
if (reader != null)
{
result = reader.Read<Models.Request>()[0] as Models.Request;
result.reviews = reader.Read<Models.Review>() as IEnumerable<Models.Review>;
}
The Request Class has a field as such:
public IEnumerable<Models.Review> reviews;
The stored procedure looks like this:
ALTER PROCEDURE [dbo].[Request_s]
(
#id int = null
)
AS
BEGIN
SELECT *
FROM [biospecimen].requests as bn
where bn.id=coalesce(#id, bn.id)
order by bn.id desc;
if #id is not null
begin
SELECT
*
FROM [biospecimen].reviews as bn
where bn.request_id = #id;
end
END
In the first read, Dapper ignores the field reviews, and in the second read, Dapper loads the information into the field. If a null set is returned, Dapper will load the field with a null set just like it will load the parent class with null contents.
The second select statement then reads the collection needed to complete the object, and Dapper stores the output as shown.
I have been implementing this in my Repository classes in situations where a target parent class has several child classes that are being displayed at the same time.
This prevents multiple trips to the database.
You can also use this approach when the target class is a child class and you need information about the parent class it is related to.

VAADIN: Why I can't set a converter to a ComboBox?

I've made a converter:
public class BooleanToDateConverter implements Converter<Boolean, Date> {
private static final long serialVersionUID = 1L;
#Override
public Date convertToModel(Boolean value, Class<? extends Date> targetType, Locale locale)
throws com.vaadin.data.util.converter.Converter.ConversionException {
if (value == true) {
return new Date();
} else {
return null;
}
}
#Override
public Boolean convertToPresentation(Date value, Class<? extends Boolean> targetType, Locale locale)
throws com.vaadin.data.util.converter.Converter.ConversionException {
if (value == null) {
return false;
} else {
return true;
}
}
#Override
public Class<Date> getModelType() {
return Date.class;
}
#Override
public Class<Boolean> getPresentationType() {
return Boolean.class;
}
}
Then I have a Vaadin ComboBox myComboBox
I try to set my converter to it:
myComboBox.setConverter(new BooleanToDateConverter());
Then I get an error in Eclipse saying:
The method setConverter(Class<?>) in the type AbstractField<Object> is not applicable for the arguments (BooleanToDateConverter)
However, I've seen other converters being used similarly and they don't get errors. Why?
Your code cannot be compiled because there is no setConverter() method available on class ComboBox that fits your custom converter. Let me explain how converters are used on select components and what is the idea behind the specific method signatures you find for setting converters on a ComboBox.
ComboBox provides two overloaded versions of setConverter():
setConverter(Class<?> datamodelType): set a pre-registered converter for the given data model type
setConverter(Converter<Object, ?> converter): set a concrete converter instance
Both of these methods are actually inherited from class AbstractField<T> where T is the data type managed by the field (e.g. Strings for text fields, Date for a DateField, Object for ComboBoxes). A converter is typically used to convert between a presentation type (such as the textual representation of a value on the UI) and its internal model type (such as a date, a monetary value or a custom JavaBean). So, for instance, if you have a Label you can use a StringToDateConverter to correctly display a Date object, which has been set as the value of the Label, in a properly localized way.
How is that with select components such as ComboBox? Here the type T is Object. The data type of a select component actually represents the item ID of the selected item from the underlying container data source. So, if you use a BeanItemContainer as the data source of a ComboBox, the container's item IDs (and hence the selected value of the ComboBox) are the contained JavaBean objects themselves. The concrete type of the item IDs depends on the container implementation used. Therefore, select components are Field components with value type Object. In other words, select components use Object as presentation type.
That is why you can only set a converter instance on a select component whose generic PRESENTATION type is Object. The model type can be chosen freely. And this also explain why you can't set a converter with presentation type Boolean and model type Date on a ComboBox -- ComboBox doesn't use Boolean as presentation type.
I wrote a blog post about Vaadin FieldGroups which also provides a good example for a use case when to use a Converter<Object, ?> on a ComboBox. You can find this article at http://blog.oio.de/2014/04/25/select-nested-javabeans-vaadin-fieldgroup/.
I don't know what you want to achieve with your code, because a converter between a presentation type of Boolean and a model type of Date doesn't make much sense. I can only guess that you want to implementat some sort of decision logic, maybe to decide whether or not a date has been set? In that case you need to take a different approach.
For reference, have a look at the Book of Vaadin on Converters.

Cast Observable Collection from base Class to inherited class

I'm writing a WPF application and I'm currently refactoring some reused code to a base ViewModel Class which my other viewmodels can inherit from.
One Property field on this base class is
public class MessageParentBase
{
MessageParentBase() {}
public string Name;
}
internal ObservableCollection<MessageParentBase> _GridData = new ObservableCollection<MessageParentBase>();
I have a subsequent property declaration
public ObservableCollection<MessageParentBase> GridData
{
get { return _GridData; }
set { _GridData = value; }
}
This works great and everything my issue is that the inerited classes actually use the follow class
Public class ChatMessage : MessageParentBase
{
public string Message;
}
and the view contains a grid of data which is bound to this GridData property but the column which should be bound to the Message field from the ChatMessage class is blank and the fields found in the MessageParentBase class are populated.
So I presume there is an issue with the view not knowing to cast up to the ChatMessage from the MessageParentBase class.
Can I inform the view that the objects will be of the type "ChatMessage".
I did try moving the property declaration up to the inherited viewmodel as
public ObservableCollection<ChatMessage> GridData
{
get { return _GridData; }
set { _GridData = value; }
}
but this gives me the following error:-
Cannot implicitly convert type 'System.Collections.ObjectModel.ObservableCollection' to 'System.Collections.ObjectModel.ObservableCollection'
Do I need to cast at the view level or can I change the viewmodels to implement this better?
Any suggestions would be greatly appreciated.
Emlyn
Change the collection to this:
public ObservableCollection<MessageParentBase> GridData { get; set; }
then add into your constructor
this.GridData = new ObservableCollection<MessageParentBase>();
Since WPF uses reflection to retrieve bound data from the data context it should be able to get the values of the derived classes stored in that collection.
Also when you run your application check the output window with Debug selected, the XAML engine will output any binding errors there.
Your ViewModel should contain a list with the type that your grid will show (in this case, the ChatMessage type). You can still use the inheritance to call common methods, but the binded list must be of the ChatMessage type

Entity Framework 4 Binding a related field to a DataGridView column

I have a DataGridView that is bound - via a binding source - to a list of entities:
VehicleRepository:
private IObjectSet<Vehicles> _objectSet;
public VehicleRepository(VPEntities context)
{
_context = context;
_objectSet = context.Vehicles;
}
List<Vehicle> IVehicleRepository.GetVehicles(Model model)
{
return _objectSet
.Where(e => e.ModelId == model.ModelId)
.ToList();
}
In my presenter
private List<Vehicle> _vehicles;
...
_vehicles = _vehicleRepository.GetVehicles(_model);
_screen.BindTo(_vehicles);
in my view
public void BindTo(List<Vehicle> vehicles)
{
_vehicles = vehicles;
if (_vehicles != null)
{
VehicleBindingSource.DataSource = _vehicles;
}
}
This works fine - my grid displays the data as it should. However, in the grid I am wanting to replace the ModelId column with a description field from the Model table. I've tried changing the binding for the column from ModelId to Model.ModelDescription but the column just appears blank.
I'm pretty sure that the data is being loaded, as I can see it when I debug, and when the same list is passed to a details screen I can successfully bind the related data to text fields and see the data.
Am I doing something obviously wrong?
It's a bit manual, but it 'works on my machine'.
Add a column to your DataGridView for the description field and then after you set your DataSource iterate through like so.
Dim row As Integer = 0
foreach (entity In (List<Entity>)MyBindingSource.DataSource)
{
string description = entity.Description;
MyDataGridView.Rows[row].Cells["MyDescriptionCell"].Value = description;
row ++;
}
You get a readonly view of your lookup. I make the new column readonly, but you could write something to handle the user changing the field if you wanted updates to run back to the server. Might be messy though.
The answer involves adding unbound read only columns and setting their value in the DataGridView's DataBindingComplete event
as described here
You can just add a column to your DataGridView, and in the DataPropertyName you must set the [entity].[Field name you need] in your case you could do: VehiclesType.Description
then you must add another binding source for the VehiclesTypes to the form, fill it using your context, and your good to go ;)

Resources