I have a bunch of POCOs that all relate to each other in a big tree. For example, this is the top-level element:
public class Incident : Entity<Incident>
{
public virtual string Name { get; set; }
public virtual DateTime Date { get; set; }
public virtual IEnumerable<Site> Sites { get; set; }
public Incident()
{
Sites = new HashSet<Site>();
}
}
The tree goes something like Incident -> Sites -> Assessments -> Subsites -> Images. The POCO's don't have any logic, just a bunch of properties. What I want to do is just fill every property with random dummy data so I can write some search code. What's the best way of doing this if I want to create a large number of dummy data?
I would consider using NBuilder. It lets you do just that - create random data for your objects, using a pretty straightforward syntax. For example:
var products = Builder<Product>.CreateListOfSize(100)
.WhereTheFirst(5)
.Have(x=>x.Title = "something")
.AndTheNext(95)
.Have(x => x.Price = generator.Next(0, 10));
Related
I have a scenario where if certain features are deployed then a number of columns will be there in some tables otherwise won't so the mapping of Entities and Columns is not static. I need to add/remove the mapping at runtime. Is there any way?
Prepare a new MappingSchema and pass to DataConnection constructor.
Consider you have the following class:
[Table]
class SampleClass
{
[Column] public int Id { get; set; }
[Column] public int Value { get; set; }
}
To remove column from full object materialization, do the following:
var ms = new MappingSchema();
ms.GetFluentMappingBuilder()
.Entity<SampleClass>().Property(e => e.Value).IsNotColumn();
// cache somewhere this schema
using (var db = new DataConnection(ms))
{
var result = db.GetTable<SampleClass>().ToArray();
}
Remember, better to cache this new MappingSchema and reuse. Otherwise you will never have cache hit and you'll lose performance.
I am working on an asp.net mvc-5 with Entity framework 6. now currently i am not using any kind on generic repositories , as the ones mentioned here:-
Link-1
&
Link-2
now the generic repository gives you a feeling that you can do everything in a generic way.. but inside these 2 links seems what can be generilzed are the basic operations for get, add, delete & modify which are by defualt provided inside Entity framework. so can anyone adivce on thses question regading using Generic repositories with EF-6 & MVC-5:-
1.is it really a good approach of using Generic repo ? as seems generic repo will just provide what EF already provide !!
2.let say i have two Parent/Child (DataCenter/Zone) objects:-
public class DataCenter
{
public int ID { get; set; }
public string Name { get; set; }
public byte[] timestamp { get; set; }
public virtual ICollection<Zone> Zones { get; set; }
}
public class Zone
{
public int ZoneID { get; set; }
public string Name { get; set; }
public int DataCenterID { get; set; }
public virtual DataCenter DataCenter { get; set; }
}
now using the Generic repository i can Get,Add,Edit,Delete these 2 objects using the same generic repo methods. but let say i want to retrieve all the Zones related to a specific Datacenter as follow:-
var results = entity.DataCenters.SingleOrDefault(a => a.ID == id).Zones.Where(a => a.Name.Contains("1"));
so can the generic repository support such a query , in a way that i can re-use the query with another object types (other than Datacenter & zones). for example to have a generic query :- to get a parent object by ID and for its child to get the childs that have their names contain the word "1" ?? and what if the parent have multiple child types !! will the generic repository support non-generic queries and operations ?
I went through the same question... I first did a specific repository, then I changed to a generic. But I've ended up having to code so much specific queries, that I decide to change for non-generic repositories, returning ToList (I didn't want IQueryable) and using Unit of Work pattern. Now I think I'm happy with the way things are.
Edit:
Query the child by it's property, bringing back the parent too (is that what you want?):
return await _context.Entity.Include(e => e.Parent)
.Where(e => e.SomeProp == someParam)
.ToListAsync();
Or, Querychild, using some property in the parent, bringing back The parent:
return await _context.Entity.Include(e => e.Parent)
.Where(e => e.Parent.SomeProp == someParam)
.ToListAsync();
I have a Asp.net MVC grid.
My problem is I need to display multiple columns in a single row.
For example:
Name Date Compensation
Id USD - 99999
Grade INR - 99999
The above layout is a single row in the grid.
All the columns (Name, Id, Grade, Curency1, Amount1, Currency2, Amount2 ) are available in a single record as separate columns. Here Currency1 means USD and Currency2 means INR.
Any ideas how to do this. I am using a strongly typed model and EF6.
I think the best way to do this would be to create a separate 'type' and model for each multi-faceted column, then try to display this type in the webgrid (which I show is possible in the latter part of my example).
For example:
Create a new 'type' (or 'column') class called CompensationColumn:
...
using System.Web.Mvc;
namespace yourproject.Columns // I put this in its own namespace/folder - you don't have to
{
public class CompensationColumn
{
public string Currency1 { get; set; }
public int Amount1 { get; set; }
public string Currency2 { get; set; }
public int Amount2 { get; set; }
public CompensationColumn(string currency_1, int amount_1, string currency_2, int amount_2)
{
Currency1 = currency_1;
Amount1 = amount_1;
Currency2 = currency_2;
Amount2 = amount_2;
}
}
}
Then create a file called CompensationColumn.cshtml in the yourproject/Shared/EditorTemplates folder (if the Shared folder doesn't exist you can also create a your view/DisplayTemplates folder). Define how this column will look, as if it was a custom 'type' (modify this to your liking):
#model yourproject.Columns.CompensationColumn
#if (Model != null)
{
#Model.Currency1<text> - </text>#Model.Amount1<text><p/></text>
#Model.Currency2<text> - </text>#Model.Amount2
}
else
{
}
Then in your Models folder, create a partial class to extend your current EF table model (file name shouldn't matter). I am going to assume your table is 'employee_table'. I am also adding Metadata for the model in this class as it is a good place to put it if you are using a database-first design:
using System.Web.Mvc;
using yourproject.Columns;
namespace yourproject.Models
{
[MetadataType(typeof(EmployeeModelMetaData))] // This links the metadata class below
public partial class employee_table // This should be the EF class name
{
[DisplayName("Compensation")]
public CompensationColumn Compensation { get; set; } // Here we add a new field for your row
}
public class EmployeeModelMetaData
{
// copy your EF class fields here and decorate them with dataannotations. This is helpful
// if you are using a database-first design as it won't get overwritten when db changes.
[DisplayName("Id")]
public int emp_id { get; set; }
[DisplayName("Amount")]
[DisplayFormat(DataFormatString = "{0:c}", ApplyFormatInEditMode = true)]
public int emp_amount1 { get; set; }
// etc . . .
}
}
I make a few assumptions here about a database-first design, but you should be able to figure out how to adapt it to a code-first design if needed.
If you also need to edit elements this column type together, then you would need to create a model binder, but I'm not going there since you only mentioned displaying it.
To get the display template to display in the webgrid, you will need to format: the columns of the webgrid. In your view with an IEnumerable model (e.g. your Index view):
#{
var grid = new WebGrid(Model);
List<WebGridColumn> columns = new List<WebGridColumn>();
WebGridColumn col = grid.Column(columnName: "Col3", header: "Compensation", format: (item) =>
{
yourproject.Columns.CompensationColumn c = item.Compensation; return Html.DisplayFor(model => c);
} );
columns.Add(col);
}
#grid.GetHtml(columns: columns)
This last snippet I adapted from Frédéric Blondel's code here
Take a look the classes below:
public class Produt
{
public virtual int id { get; set; }
public virtual string name { get; set; }
[ScriptIgnore]
public virtual Unit unit { get; set; }
}
public class Unit
{
public virtual int id { get; set; }
public virtual string name { get; set; }
public virtual IList<Produt> produts { get; set; }
}
After this, the mappings:
public partial class ProdutMap : ClassMap<Produt>
{
public ProdutMap()
{
Id(x => x.id).GeneratedBy.Identity();
Map(x => x.name).Length(100).Not.Nullable();
References(x => x.unit, "idUnit").Cascade.All().LazyLoad();
}
}
public partial class UnitMap : ClassMap<Unit>
{
public UnitMap()
{
Id(x => x.id).GeneratedBy.Identity();
Map(x => x.name).Length(100).Not.Nullable();
HasMany(x => x.produts).Cascade.All().KeyColumns.Add("idUnit").LazyLoad();
}
}
Now, imagine that I want to execute this query:
SELECT produt.id, produt.name, unit.name FROM Produt, Unit WHERE produt.idUnit = unit.id
with nhibernate? How to do? Something help?
P.S. The [ScriptIgnore] is because I had problems with circular references. My classes are not only these. This is just an example.
Just fetch Products
The simplest way to do this is to just fetch a list of Products. Product already contains all of the information you need because it has a reference to Unit.
// NOTE: This fetches ALL products. You really should limit this.
var products = session.Query<Product>();
foreach (var product in products)
Console.WriteLine("Product: {0}, Unit: {1}", product.Name, product.Unit.Name);
On each iteration of this loop, if product.Unit points to a unit that NHibernate has not fetched yet, NHibernate will lazily execute another query to fetch that unit.
Sometimes you are not able to use lazy loading - perhaps you need to close the NHibernate session before iterating over the results. Also, for performance it would be better to reduce the number of round-trips to the database. We can fix these problems by changing our query like so:
var products = session.Query<Product>().Fetch(x => x.Unit);
Flatten your results
If for some reason you need flattened result objects where you don't have to dig through nested objects to get the data you need, you can use "projections" to do this. With LINQ, this looks like:
var productInfos = session.Query<Product>().Select(x => new
{
ProductId = x.Id,
ProductName = x.Name,
UnitName = x.Unit.Name
});
This is also useful if you need to limit the columns returned by NHibernate - for example, if one of the column contains huge BLOBs that you want to avoid fetching.
Besides LINQ, NHibernate has several different ways to execute queries: native SQL, HQL, Criteria, and QueryOver. For Criteria or QueryOver, the AliasToBean result transformer will help you when executing these types of queries. See this related question for an example using AliasToBean in a Criteria query: NHibernate - Only retrieve specific columns when using Critera queries?
Does it make sense create an object that contains only those properties that the user will input on the webpage, use that for binding in the controller, and then map to the full Entity Object? Or should you just use the entity object, and use Include and Exclude to make restrictions on what gets bound on input?
I have come to like the idea of using interfaces to segregate which properties should be included when the object is updated.
For example:
To create and update an person object:
interface ICreatePerson
{
string Name { get; set; }
string Sex { get; set; }
int Age { get; set; }
}
interface IUpdatePerson
{
string Name { get; set; }
}
class Person : ICreatePerson, IUpdatePerson
{
public int Id { get; }
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
}
Then, when binding model, just use the appropriate interface as the type and it will only update the name property.
Here is an example controller method:
public ActionResult Edit(int id, FormCollection collection)
{
// Get orig person from db
var person = this.personService.Get(id);
try
{
// Update person from web form
UpdateModel<IUpdatePerson>(person);
// Save person to db
this.personService.Update(person);
return RedirectToAction("Index");
}
catch
{
ModelState.AddModelErrors((person.GetRuleViolations());
return View(person);
}
}
See this article (and the comments) for a very good discussion of the options.
I recommend using a separate presentation model type in most cases. Aside from the issue of binding (which is important, but there are other ways around this issue), I think that there are other reasons why using presentation model types is a good idea:
Presentation Models allow "view-first" development. Create a view and a presentation model at the same time. Get your user representative to give you feedback on the view. Iterate until you're both happy. Finally, solve the problem of mapping this back to the "real" model.
Presentation Models remove dependencies that the "real" model might have, allowing easier unit testing of controllers.
Presentation Models will have the same "shape" as the view itself. So you don't have to write code in the view to deal with navigating into "detail objects" and the like.
Some models cannot be used in an action result. For example, an object graph which contains cycles cannot be serialized to JSON.