Currently when using OrmLite library from ServiceStack if I want single entity selected I do:
AppUser user = db.First<AppUser>(q => q.Id == id);
However since Single is more precise (obviously I want exception thrown if somehow multiple users with same id ended up in database) I was wondering if there is overload that I can use. Currently when I do db.Single I just get that overload with manual filtering:
public static T SingleOrDefault<T>(this IDbConnection dbConn, string filter);
OK, I found what the issue is - the version I'm using (3.9.71) doesn't have that overload - it was added later:
https://github.com/ServiceStack/ServiceStack.OrmLite/commit/f2f5f80f150f27266bdcaf81b77ca60b62897719#diff-e9a84724e6a8315ec7f7fc5a5512a44b
Seems I'll need to extend that class from within my code.
Related
There seems be some things missing in the Spring-LDAP ODM annotations. This is a question by way of a feature request, if there is a better way to contribute such requests, please say so.
I'd like to mark an #Attribute as read-only, so it will populate the bean from LDAP for reference, but not persist it back to ldap. I'd suggest adding an attribute read-only to #Attribute, defaulting to false, for the usual case. The default attributes of * misses all the operational attributes, some of which are very useful, and transfers more data than is required, slowing down the ldap query with attributes which will never be used.
An example of this; it would be very useful, for literally read only, such as entryUUID, etag, etc., which you cannot use if you wish to persist only some fields back to ldap, as the bean fails to persist to ldap with an exception when you save the bean. But also would be usefule for general fields which you want to structurally prevent the user from ever updating.
You can get around this by not annotating read-only fields, and then manually populating the read only fields with a separate call. Very messy and kills the query speed.
Also on a related topic, query() coudl have a default list of attributes, which you have already annotated in your classes, something like :
public static String[] getBeanAttributes(Class<?> beanClass) {
ArrayList<String> attrsObj = new ArrayList<>();
for (Field field : beanClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Attribute.class)) {
Attribute attr = field.getAnnotation(Attribute.class);
attrsObj.add(attr.name());
}
}
String[] attrs = attrsObj.toArray(new String[attrsObj.size()]);
return attrs;
}
Above just returns a simple String[] of your declared attributes, to pass to query.attributes() - now i realize that as a static member, query() is built before the bean class is known, but at least there could be a helper function like the above, or a method signature for query attributes() that took a bean Class signature as an argument.
I created LDAP-312 on Jira. Thanks.
Is there a way we can use ObjectContext with DbContext's ModelBuilder? We don't want to use POCO because we have customized property code that does not modify entire object in update, but only update modified properties. Also we have lots of serialisation and auditing code that uses EntityObject.
Since poco does create a proxy with EntityObject, we want our classes to be derived from EntityObject. We don't want proxy. We also heavily use CreateSourceQuery. The only problem is EDMX file and its big connection string syntax web.config.
Is there any way I can get rid of EDMX file? It will be useful as we can dynamically compile new class based on reverse engineering database.
I would also like to use DbContext with EntityObject instead of poco.
Internal Logic
Access Modified Properties in Save Changes which is available in ObjectStateEntry and Save them onto Audit with Old and New Values
Most of times we need to only check for Any condition on Navigation Property for example
User.EmailAddresses.CreateSourceQuery()
.Any( x=> x.EmailAddress == givenAddress);
Access Property Attributes, such as XmlIgnore etc, we rely heavily on attributes defined on the properties.
A proxy for a POCO is a dynamically created class which derives from (inherits) a POCO. It adds functionality previously found in EntityObject, namely lazy loading and change tracking, as long as a POCO meets requirements. A POCO or its proxy does not contain an EntityObject as the question suggests, but rather a proxy contains functionality of EntityObject. You cannot (AFAIK) use ModelBuilder with EntityObject derivatives and you cannot get to an underlying EntityObject from a POCO or a proxy, since there isn't one as such.
I don't know what features of ObjectContext does your existing serialisation and auditing code use, but you can get to ObjectContext from a DbContext by casting a DbContext to a IObjectContextAdapter and accessing IObjectContextAdapter.ObjectContext property.
EDIT:
1. Access Modified Properties in Save Changes which is available in ObjectStateEntry and Save them onto Audit with Old and New Values
You can achieve this with POCOs by using DbContext.ChangeTracker. First you call DbContext.ChangeTracker.DetectChanges to detect the changes (if you use proxies this is not needed, but can't hurt) and then you use DbCotnext.Entries.Where(e => e.State != EntityState.Unchanged && e.State != EntityState.Detached) to get DbEntityEntry list of changed entities for auditing. Each DbEntityEntry has OriginalValues and CurrentValues and the actual Entity is in property Entity.
You also have access to ObjectStateEntry, see below.
2. Most of times we need to only check for Any condition on Navigation Property for example:
User.EmailAddresses.CreateSourceQuery().Any( x=> x.EmailAddress == givenAddress);
You can use CreateSourceQuery() with DbContext by utilizing IObjectContextAdapter as described previously. When you have ObjectContext you can get to the source query for a related end like this:
public static class DbContextUtils
{
public static ObjectQuery<TMember> CreateSourceQuery<TEntity, TMember>(this IObjectContextAdapter adapter, TEntity entity, Expression<Func<TEntity, ICollection<TMember>>> memberSelector) where TMember : class
{
var objectStateManager = adapter.ObjectContext.ObjectStateManager;
var objectStateEntry = objectStateManager.GetObjectStateEntry(entity);
var relationshipManager = objectStateManager.GetRelationshipManager(entity);
var entityType = (EntityType)objectStateEntry.EntitySet.ElementType;
var navigationProperty = entityType.NavigationProperties[(memberSelector.Body as MemberExpression).Member.Name];
var relatedEnd = relationshipManager.GetRelatedEnd(navigationProperty.RelationshipType.FullName, navigationProperty.ToEndMember.Name);
return ((EntityCollection<TMember>)relatedEnd).CreateSourceQuery();
}
}
This method uses no dynamic code and is strongly typed since it uses expressions. You use it like this:
myDbContext.CreateSourceQuery(invoice, i => i.details);
There is Campaign Entity and for that, I have CampaignRepository which have this functions
public IList FindAll();
public Campaign FindByCampaignNumber(string number);
But now i want this criterias -:
Find campaigns that are created today.
Find campaigns that are created in this month
Find top 5 latest campaigns.
Find campaigns that are created in this year.
So for all these campaigns filters,
Do i create separate function for each of them in repository ?
and implement like this way.
Getall campaigns and then filter required campaigns, but i do not want all campaigns. While searching in google i find this solution's
1: http://russelleast.wordpress.com/2008/09/20/implementing-the-repository-and-finder-patterns/
Is there any method i can avoid multiple functions or do i go ahead and create seperate functions for each of this filter ?
Have you considered implementing Specification pattern in your application? Maybe it looks like an overkill, but it may prove useful if your app will have some complex user filter options.
class CampaignSpecification
{
public CampaignSpecification Number(string number);
public CampaignSpecification DateBetween(DateTime from, date to);
public CampaignSpecification Year(DateTime year);
} //I have omitted all the AND/OR stuff it can be easily implemented with any SQL like query language
Here is an example how loading from the repository may look like
var campaignList = CampaignRepository.load(
new CampaignSpec()
.Number("2")
.Year(DateTime.Now);
Also I'd like to add that it depends much on what kind of data access solution you are using, it makes implementing easier when you know what kind of API you will be using(Criteria API, SQL or whatever) so you can tweak your Specification interface to make its implementation simpler.
UPDATE: if you are implementing specifications in .NET using linq and nHibernate please check out http://linqspecs.codeplex.com/
I would go with creating two Specifications: TopCampaignSpec and CampaingCreatedSpec.
var spec = CampaignCreatedSpec.ThisYear();
var campaigns = CampaignsRepository.FindSatisfying(spec);
CampaingCreatedSpec can also be replaced with more generic DateRange class if you need this functionality elsewhere:
var thisYear = DateRange.ThisYear();
var campaigns = CampaignsRepository.FindByDateRange(spec);
I also highly recommend staying away from 'generic' repositories and entities. Please read this
From DDD perspective it does not matter whether data access code is implemented as SQL/HQL/ICriteria or even web service call. This code belongs to repository implementation (data access layer). This is just a sample:
public IList<Campaign> FindByDateRange(CampaignCreatedSpec spec) {
ICriteria c = _nhibernateSession.CreateCriteria(typeof(Campaign));
c.Add(Restrictions.Between("_creationDate", spec.StartDate, spec.EndDate));
return c.List<Campaign>();
}
Here is how I would do this:
class Campaigns{
IEnumerable<Campaign> All(){...}
IEnumerable<Campaign> ByNumber(int number){...}
IEnumerable<Campaign> CreatedToday(){...}
IEnumerable<Campaign> CreatedThisMonth(){...}
IEnumerable<Campaign> CreatedThisYear(){...}
IEnumerable<Campaign> Latest5(){...}
private IQueryable<Campaign> GetSomething(Something something){
//used by public methods to dry out repository
}
}
Reasoning is simple - it matters by what You are interested to look for campaigns (that knowledge is part of Your domain). If we explicitly state functions to reflect that, we will always know it.
Is it appropriate to add all this methods in campaign repository ?
I don't see anything wrong with that.
Arnis i want some code, how u implementing Created today function in domain itself, Are you injecting repository here in this function ? Thanks for your cooperation
I wouldn't implement CreatedToday function in my domain. It would sit in repository and repository implementations should not be concern of domain. If You mean how I would use Campaign repository and if it should be used from domain - no, it should not be used from within of domain. If You mean if I would inject repository inside of repository - You are listening too much of xzibit.
You should be able to do all of the above with the following repository method:
List<Campaign> findCampaigns(Date fromCreationDate, Date toCreationDate, int offset, Integer limit) {
if (fromCreationDate != null) add criteria...
if (toCreationDate != null) add criteria...
if (limit != null) add limit...
}
This is how I do it and it works very well.
Is it possible to use ASP.NET Dynamic Data with SubSonic 3 in-place of Linq to SQL classes or the Entity Framework? MetaModel.RegisterContext() throws an exception if you use the context class that SubSonic generates. I thought I remembered coming across a SubSonic/Dynamic Data example back before SubSonic 3 was released but I can't find it now. Has anyone been able to get this to work?
I just got Subsonic 3.0.0.4 ActiveRecord working last night in Visual Studio 2010 with my SQLite database after a little bit of work and I've tried to document the steps taken here for your benefit.
Start by adding a New Item -> WCF Data Service to the project you're using to host your webapp/webservices then modify it similar to my PinsDataService.svc.cs below:
public class PinsDataService : DataService<PINS.Lib.dbPINSDB>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.UseVerboseErrors = true;
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
}
At this point your Dynamic Data Service would probably be working if you matched all the database naming conventions perfectly but I didn't have that kind of luck. In my ActiveRecord.tt template I had to prepend the following two lines before the public partial class declarations:
[DataServiceKey("<#=tbl.PrimaryKey #>")]
[IgnoreProperties("Columns")]
public partial class <#=tbl.ClassName#>: IActiveRecord {
I then added references to System.Data and System.Data.Services.Client followed by the inclusion of using statements for using System.Data.Services and using System.Data.Services.Common at the top of the ActiveRecord.tt template.
The next step was to use the IUpdateable partial class implementation from this blog post http://blogs.msdn.com/aconrad/archive/2008/12/05/developing-an-astoria-data-provider-for-subsonic.aspx and change the public partial class dbPINSDB : IUpdatable to match my subsonic DatabaseName declared in Settings.ttinclude
Then to consume the data in a separate client app/library I started by adding a 'Service Reference' named PinsDataService to the PinsDataService.svc from my client app and went to town:
PinsDataService.dbPINSDB PinsDb =
new PinsDataService.dbPINSDB(new Uri("http://localhost:1918/PinsDataService.svc/"));
PinsDataService.Alarm activeAlarm =
PinsDb.Alarms.Where(i => i.ID == myAA.Alarm_ID).Take(1).ElementAt(0);
Note how I'm doing a Where query that returns only 1 object but I threw in the Take(1) and then ElementAt(0) because I kept getting errors when I tried to use SingleOrDefault() or First()
Hope this helps--also, I'm already aware that dbPINSDB is a really bad name for my Subsonic Database ;)
It could very well be that I'm just missing the correct vernacular in this space, but I'm looking for a particular piece of functionality in SubSonic. In NetTiers it was called a "DeepLoad". A deep load runs to the database and fetches many objects (ie. fetch this OrderDetail and all of it's LineItems) in one database call.
Again, I want to run to the data store once an build up a potentially dense object graph or related items populated by the data store.
How do I do this in SubSonic and what is it called in SubSonic?
You can do this in SubSonic 3.0 (not yet released, but almost there...) using IQueryable with lazy loading:
var db=new NorthwindDB();
var order=db.Orders.Where(x=>.xID==20).SingleOrDefault();
Assert.Equal(3,order.OrderDetails.Count());
if you're not on 3 (which requires .net 3.5) you can do this with Active record as Paul mentions - but it will make two calls.
There is no eager loading, and DeepSave in ActiveRecord only calls Save.
Here is an example with Northwind Order class foreign key method.
[Test]
public void SelectOrderDetails()
{
Order order = new Order(10250);
OrderDetailCollection details = order.OrderDetails();
Assert.IsTrue(details.Count == 3);
}