I have just started using Linq2sql, it generates all of the Classes after my tables which is awesome. my problem is that i have a lot of objects that have the same name as my tables.
this is forcing my to fully namespace everything which i don’t really like as i think it makes my code look messy.
Has anyone found an elegant way to get around this?
ps: i know about namespace aliases and im not really a fan.
If this really is an issue for you, you can change the name of your generated table items in the Linq designer. Select the table and change the value in the Name field in the properties (L2S keeps track of the source table as a separate item, so the two don't have to be named the same). Note that regenerating your DBML file will wipe these changes out.
Along the lines of Rails convention (which I use in my .net) frequently I will name the database table the plural name and the class the single name eg. Table = Users vs. Class = User.
You could try turning off pluarisation of the names it generates.
Tools -> Options -> Database Tools -> O/R Designer
Related
Hello I am having the following situation in my models:
class Package(models.Model):
name
class SetOfItems(models.Model)
name
class Item(models.Model):
package(FK)
setofitems(FK)
And the problem I am trying to solve is to simplify queries from SetOfItems. E.g. in case I would need to get a package name from SetOfItems, I would need to write something like
SetOfItems.objects.values('item__package__name'), which actually does not work, well in admin site (e.g. if I am creating an extra field there).
So what I am looking for is to store the information about Packages in SetOfItem model without making a direct relation (as I think that if I will put a FK there the data integrity will suffer, e.g. it will be possible to have on package inside Item and another one in SetOfItems)..
So maybe there is some possibility to have SQL view, or something like this... to have a table column automatically pre-filled from other table? Or something else?
Item is the through table in a many-to-many relationship between Package and SetOfItems. So you should declare it as such:
class SetOfItems(models.Model):
packages = models.ManyToManyField(Package, through='Item')
This doesn't change your actual table structure at all, but it allows you to do my_package.setofitems.all().
My problem is that when i drag tables to dbml ,(there are 2 tables ,they have 3 relations with each other that i named these relation in my own pattern) , after drag in dmbl these relation renamed to ralation1 , relation2 , relation3 , and these aren't the truth names.
i need to access to my truth name of relations .
why dbml changes names of relations after map ??
how to do this to don't happen this event??
please help me if any one has idea.
thankes
It is unclear in your question if you are renaming the associations in the DBML (through the designer or XML) or in the .Designer file directly. If you modify the .Designer file, any changes you make will be overwritten the next time you change the design surface. If you want changes to be retained, make sure to make the modification in the designer or XML, but not the .Designer file.
If you are doing something else, it might help by providing some steps to reproduce the issue including code.
I have a table Users and a table Items
In the Items table, I have fields such as
ModifiedBy
CreatedBy
AssignedTo
which all have a userId integer. The database is set up to have these as foreign keys back to the Users table.
When using LINQToSQL, the relationships which are automatically built from the dbml end up giving me names like User, User1 and User2
e.g. myItem.User1.Name or myItem.User2.Name
Obviously this isn't very readable and I'd like it be along the lines of
myItem.CreatedByUser.Name or myItem.ModifiedByUser.Name etc
I could change the names of the relationships but that means I have to redo that every time I change the db schema and refresh the dbml.
Is there any way round this?
The simple answer: No.
Someone has suggested the idea of creating partial Association classes where the property names get defined, but that won't work either: Renaming LINQ 2 SQL Entity Properties Through Partial Classes.
Your choice is to either spend a little time learning more about LINQ-to-SQL "behind-the-scenes" so that you can manually make the necessary modifications or to just change the property names through the Properties window. Personally, I just delete/redrag/rename, because not setting a property correctly is a pain to debug because the exceptions that get thrown give you little to no clue as to what caused it. I even went so far as to create a unit test library that takes each MetaTable object in the model and verifies the field count, the ServerDataType contents of each field, the association count, the names of each association, and the names of each end of the association. Every few changes, I run the unit tests to make sure that the model is intact.
Firstly, no... the names are created based on the second table in the relationship.
But what you should know is that you don't have to "refresh" (meaning, delete the table in the DBML then re-drag-and-drop it).
For the project I'm working on, we have over 200 tables... about 50 of which we have manually tweaked after dragging them from the database. We never delete and re-drag tables as there have been so many changes post-auto-generation.
I just add a small partial class to extend the object with suitably named properties, example below:
namespace Database.TableModels {
partial class WTSR_Induction {
public EmailTemplate ConfirmationEmailTemplate {
get { return EmailTemplate1; }
}
public EmailTemplate InviteEmailTemplate {
get { return EmailTemplate; }
}
}
}
In this example, the WTSR_Inductions table has two links to the EmailTemplates table, hence the EmailTemplate and EmailTemplate1 properties.
A bit late but you can do this by selecting the relationship on the linq model and go to properties and update the parent property name.
You could use linq to sql without the dbml it may be extra work upfront but from the perspective of a change to a table column name it may be easier than changes to the dbml as you have described.
I suggest creating extension methods mapping the names you want to the names you get from the autogenerated code. That way after each auto-generation you don't have to change the autogenerated code, but only your own extension methods. That, plus the unit tests to do sanity checks as suggested elsewhere on this page should work fine.
I have just faced this problem myself and I'm off to try to implement my own suggestion.
EDIT: This seems relevant:
SQLMetal Multiple Foreign Keys Pointing to One Table Issue
My SQL tables names are all plural - Events, Teams, Campuses, etc...
When I drag the tables in to the dbml, it creates an entity called "Campuse" which of course is incorrect. I manually rename that to Campus in the properties page, but it doesnt seem to update all of the auto generated code correctly. For example, the .designer.cs file has the following code:
public System.Data.Linq.Table<Campus> Campus
when it should be
public System.Data.Linq.Table<Campus> Campuses
Similar problems with association names.
I could probably go through all of that generated code, and try to rename everything manually, but that's a pain. Is there a better way?
You can turn off automatic pluralization of LINQ-to-SQL entities, and that should correct your problem. Unfortunately, LINQ-to-SQL (and the Entity Framework) are designed to work with the much more prevalent practice of naming tables in singular form. The code generator will try to figure out the singular form of what it sees as a plural word, but it's not particularly adept at this task.
I am trying to inherit from my generated datacontext in LinqToSQL - something like this
public class myContext : dbDataContext {
public System.Data.Linq.Table<User>() Users {
return (from x in base.Users() where x.DeletedOn.HasValue == false select x);
}
}
But my Linq statement returns IQueryable which cannot cast to Table - does anyone know a way to limit the contents of a Linq.Table - I am trying to be certain that anywhere my Users table is accessed, it doesn't return those marked deleted. Perhaps I am going about this all wrong - any suggestions would be greatly appreciated.
Hal
Another approach would to be use views..
CREATE VIEW ActiveUsers as SELECT * FROM Users WHERE IsDeleted = 0
As far as linq to sql is concerned, that is just the same as a table. For any table that you needed the DeletedOn filtering, just create a view that uses the filter and use that in place of the table in your data context.
You could use discriminator column inheritance on the table, ie. a DeletedUsers table and ActiveUsers table where the discriminator column says which goes to which. Then in your code, just reference the Users.OfType ActiveUsers, which will never include anything deleted.
As a side note, how the heck do you do this with markdown?
Users.OfType<ActiveUsers>
I can get it in code, but not inline
Encapsulate your DataContext so that developers don't use Table in their queries. I have an 'All' property on my repositories that does a similar filtering to what you need. So then queries are like:
from item in All
where ...
select item
and all might be:
public IQueryable<T> All
{
get { return MyDataContext.GetTable<T>.Where(entity => !entity.DeletedOn.HasValue); }
}
You can use a stored procedure that returns all the mapped columns in the table for all the records that are not marked deleted, then map the LINQ to SQL class to the stored procedure's results. I think you just drag-drop the stored proc in Server Explorer on to the class in the LINQ to SQL designer.
What I did in this circumstance is I created a repository class that passes back IQueryable but basically is just
from t in _db.Table
select t;
this is usually referenced by tableRepository.GetAllXXX(); but you could have a tableRepository.GetAllNonDeletedXXX(); that puts in that preliminary where clause to take out the deleted rows. This would allow you to get back the deleted ones, the undeleted ones and all rows using different methods.
Perhaps my comment to Keven sheffield's response may shed some light on what I am trying to accomplish:
I have a similar repository for most
of my data access, but I am trying to
be able to traverse my relationships
and maintain the DeletedOn logic,
without actually calling any
additional methods. The objects are
interrogated (spelling fixed) by a StringTemplate
processor which can't call methods
(just props/fields).
I will ultimately need this DeletedOn filtering for all of the tables in my application. The inherited class solution from Scott Nichols should work (although I will need to derive a class and relationships for around 30 tables - ouch), although I need to figure out how to check for a null value in my Derived Class Discriminator Value property.
I may just end up extended all my classes specifically for the StringTemplate processing, explicitly adding properties for the relationships I need, I would just love to be able to throw StringTemplate a [user] and have it walk through everything.
There are a couple of views we use in associations and they still appear just like any other relationship. We did need to add the associations manually. The only thing I can think to suggest is to take a look at the properties and decorated attributes generated for those classes and associations.
Add a couple tables that have the same relationship and compare those to the view that isn't showing up.
Also, sometimes the refresh on the server explorer connection doesn't seem to work correctly and the entities aren't created correctly initially, unless we remove them from the designer, close the project, then reopen the project and add them again from the server explorer. This is assuming you are using Visual Studio 2008 with the linq to sql .dbml designer.
I found the problem that I had with the relationships/associations not showing in the views. It seems that you have to go through each class in the dbml and set a primary key for views as it is unable to extract that information from the schema. I am in the process of setting the primary keys now and am planning to go the view route to isolate only non-deleted items.
Thanks and I will update more later.