How add property to EF4 - entity-framework-4

How add new property to WorkSpace which will show the name room?

This property cannot be defined in entity designer unless it is also defined in the database as column of WorkPanel table. Create partial class to generated entity and add custom property:
public partial class WorkPanel
{
public string Name
{
get
{
return (Table != null && Table.Room != null) ? Table.Room.Name : null;
}
}
}
To use this property you must always load Table and Room entity with WorkPanel (either by eager or lazy loading).

Related

Simple getter logic in ViewModels

Is it ok to have simple logic (without any dependencies) in ViewModels getters or it should contain just automatic properties? in this case just checking for null so I don't have to do that in controller each time I am using this ViewModel. TicketSearchParameters is a simple model containing string and date properties, there is no Repository or any other dependencies.
public class MyViewModel
{
private TicketSearchParameters _searchParams;
public TicketSearchParameters SearchParams
{
get
{
if (_searchParams == null)
{
_searchParams = new TicketSearchParameters();
_searchParams.CreatedFrom = DateTime.Now.AddDays(-7);
_searchParams.CreatedTo = DateTime.Now;
}
return _searchParams;
}
set
{
_searchParams = value;
}
}
/*** other properties ***/
}
You code is fairly ok. But you can use NULL Object Design Pattern to check null and create NullObject.
make a class named NullSearchParams inherited from SearchParams and initialize it when needed.
You can see Null design pattern documentation here.
https://sourcemaking.com/design_patterns/null_object

InvalidOperationException: The property is part of the object's key information and cannot be modified

I'm getting this error when I try to change column value.
Here is how I got to this problem:
1) I was needed to add this bit column to an Existing table.
ALTER TABLE BooksDB.dbo.Books
ADD edited bit NOT NULL DEFAULT(0),
2) Updated my EF model in project.
3) Now when I try to change 'edited' property of entity object, I'm getting the error from Subject line.
Why is that?
EF object declaration:
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Boolean edited
{
get
{
return _edited;
}
set
{
if (_edited != value)
{
OneditedChanging(value);
ReportPropertyChanging("edited");
_edited = StructuralObject.SetValidValue(value);
ReportPropertyChanged("edited");
OneditedChanged();
}
}
}
private global::System.Boolean _edited;
partial void OneditedChanging(global::System.Boolean value);
partial void OneditedChanged();
This problem solved by adding PRIMARY KEY to the table.

return table primary key name with tableGateway

I'm trying to create an abstract object for my Table Objects.
Today I have lots of object like: CategoriaTable, FornecedoresTable, etc that implement $this->tableGateway->insert(), $this->tableGateway->update(), etc
I created an TableAbstract that contains most of those functionallities, but I stuck on one problem:
// In CategoriaTable my table id is named cat_id
$this->tableGateway->update($object->getArrayCopy(),array('cat_id' => $object->getId()))
// But in FornecedoresTable my table id is named for_id
$this->tableGateway->update($object->getArrayCopy(),array('for_id' => $object->getId()))
How can I get from tableGateway the id of an table? There is an better way to do what I want?
I guess I could inject the id name in my object but I don't thing this is a good way to do that...
You can create new TableGateway class parameter.(In my case I created $this->primary;)
And if it is not set use Zend\Db\Metadata\Metadata to find it straight from db structure.
<?php
//...
use Zend\Db\TableGateway\AbstractTableGateway;
use Zend\Db\Metadata\Metadata;
class AbstractTable extends AbstractTableGateway
{
protected $primary;
public function getPrimary()
{
if (null === $this->primary) {
$metadata = new Metadata($this->adapter);
$constraints = $metadata->getTable($this->getTable()->getTable())
->getConstraints();
foreach ($constraints AS $constraint) {
if ($constraint->isPrimaryKey()) {
$primaryColumns = $constraint->getColumns();
$this->primary = $primaryColumns;
}
}
}
return $this->primary;
}
}
?>

Is it possible to auto update only selected properties on an existent entity object without touching the others

Say I have a bunch of boolean properties on my entity class public bool isActive etc. Values which will be manipulated by setting check boxes in a web application. I will ONLY be posting back the one changed name/value pair and the primary key at a time, say { isActive : true , NewsPageID: 34 } and the default model binder will create a NewsPage object with only those two properties set. Now if I run the below code it will not only update the values for the properties that have been set on the NewsPage object created by the model binder but of course also attempt to null all the other non set values for the existent entity object because they are not set on NewsPage object created by the model binder.
Is it possible to somehow tell entity framework not to look at the properties that are set to null and attempt to persist those changes back to the retrieved entity object and hence database ? Perhaps there's some code I can write that will only utilize the non-null values and their property names on the NewsPage object created by model binder and only attempt to update those particular properties ?
[HttpPost]
public PartialViewResult SaveNews(NewsPage Np)
{
Np.ModifyDate = DateTime.Now;
_db.NewsPages.Attach(Np);
_db.ObjectStateManager.ChangeObjectState(Np, System.Data.EntityState.Modified);
_db.SaveChanges();
_db.Dispose();
return PartialView("MonthNewsData");
}
I can of course do something like below, but I have a feeling it's not the optimal solution. Especially considering that I have like 6 boolean properties that I need to set.
[HttpPost]
public PartialViewResult SaveNews(int NewsPageID, bool isActive, bool isOnFrontPage)
{
if (isActive != null) { //Get entity and update this property }
if (isOnFontPage != null) { //Get entity and update this property }
}
API is not strongly typed but you can do it as follows. DbContext API has better support for this.
[HttpPost]
public PartialViewResult SaveNews(NewsPage Np)
{
Np.ModifyDate = DateTime.Now;
_db.NewsPages.Attach(Np);
var entry = _db.ObjectStateManager.GetObjectStateEntry(Np);
var cv = entry.CurrentValues;
if (isActive)
{
cv.SetBoolean(cv.GetOrdinal("isActive"), true);
}
_db.SaveChanges();
_db.Dispose();
return PartialView("MonthNewsData");
}
You can go for two options
Register a custom model binder for that action. In the custom model binder you have to get the complete object from the database and only update the POSTed properties.
Use a view model. Instead of directly having the NewsPage model as the action parameter. You can create a custom view model that wraps the necessary properties. Inside the action you have to make a call to db to get the complete NewsPage instance and update only the corresponding properties from the view model.
Somewhat ugly, but did the trick in my case without having to create and register custom model binder or using multiple if statements.
[HttpPost]
public void SaveNews(string propname, bool propvalue, int PageID)
{
var prop = typeof(NewsPage).GetProperties().FirstOrDefault(x => x.Name.ToLower() == propname.ToLower());
var Np = _db.NewsPages.FirstOrDefault(x => x.PageID == PageID);
prop.SetValue(Np, propvalue, null);
Np.ModifyDate = DateTime.Now;
_db.SaveChanges();
_db.Dispose();
}

Error getting foreign key data on entity

I'm new in MVC2 and Entity Framework and I tried get a list of products with the respective category name, but it's returned me the error
"Object reference not set to an instance of an object."
I have a table Product with a foreign key Category.
I'm using MVC2 and Entity Framework 4.0.
public class Repository
{
public IQueryable<Produto> ListAllProducts()
{
return entities.Produtos;
}
}
public class AdminProdutoController : Controller
{
TudoDeMassinhaRepository repository = new TudoDeMassinhaRepository();
public ActionResult Index()
{
var produtos = repository.ListAllProducts().ToList();
return View(produtos);
}
}
code in view where the error is generated: <%: item.CatProduto.cat_produto_nome%>
You're only selecting the products - you're not currently including the categories. This means: you'll get back your product objects, but any related objects they refer to are not loaded automatically - that's why the .CatProduto property will be NULL and thus you're getting the error.
You need to explicitly specify which additional entities you want to have loaded - something like:
public IQueryable<Produto> ListAllProductsWithCategories()
{
return entities.Produtos.Include("CatProduto");
}
This way, you should get back your Produto objects, and their CatProduto property should have been loaded and populated, too.
So if you change your index method to be:
public ActionResult Index()
{
var produtos = repository.ListAllProductsWithCategories().ToList();
return View(produtos);
}
it should work.

Resources