Why is Entity Framework losing my indexes? - c#

When I use a database initializer like DropCreateDatabaseAlways or MigrateDatabaseToLatestVersion to create my Entity Framework (5.0.0) database, the resulting schema does not include the indexes that I defined in my migrations, unlike when I create the database using Update-Database.
How can I configure the system so that it produces the same end result using a database initializer as it would when running the migrations in sequence?
Example migration
public override void Up()
{
CreateIndex("dbo.Users", "Username", unique:true);
}
Result from DropCreateDatabaseAlways (no index)
CREATE TABLE [dbo].[Users] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[Username] NVARCHAR (50) NULL,
[Email] NVARCHAR (255) NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Result from Update-Database (includes index)
CREATE TABLE [dbo].[Users] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[Username] NVARCHAR (50) NULL,
[Email] NVARCHAR (255) NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Username]
ON [dbo].[Users]([Username] ASC);

The approach you have used is the "manual" code first migrations. Where you get to fiddle with the script. Automated migrations or drop create, EF just bangs a script together to match the table and Foreign keys and pops it out there. ie what you would have seen in the generated class before you added code. :-)
Use Automated Migrations/Create scenarios and just call SQL Command direct afterwards to add indexes from code. You have the SQL code to create indexes. Just trigger the initializer and follow up with create Index custom routine.

Related

Migrating to identity with [Id] replacement

I have an existing database with my users. But the [Id] column is just a number
[Id] BIGINT IDENTITY (1, 1) NOT NULL
CONSTRAINT [Users] PRIMARY KEY CLUSTERED ([Id] ASC)
I want to transfer all of my users to a new AspNetUsers table where
[Id] NVARCHAR (128) NOT NULL
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
I saw all the explanations on migrating, but I couldnt find how can I generate a new Id in SQL Insert statment. All examples show only how to transfer data from the old database to a new one.
Can someone please give me an example of SQL code that copies all the data from one table and inserts it to another table with new generated unique value.
The final script that worked:
INSERT INTO AspNetUsers
(
Id,
Email,
UserName,
.
.
.
)
SELECT
CAST(NEWID() AS NVARCHAR (128)),
Email,
UserName,
.
.
.
FROM Users

Publishing a webapp to azure along with database?

I'm trying to publish a version of 'GeekQuiz' to azure as a webapp. It looks like I've managed to get everything exported except the database since information isn't being loaded in at all.
The TriviaContext is where the database appears to be created:
public class TriviaDatabaseInitializer : CreateDatabaseIfNotExists<TriviaContext>
However there were no databases defined in manage.windowsazure.com, so I created one (sql database) and got the connection string for it and ran that via the packagemanager console (Update-Database -Verbose -ConnectionString ...) then I ran Enable-Migrations -ContextTypeName GeekQuiz.Models.TriviaContext.
Everything seems to have run without issues but the webapp still doesn't work and I'm pretty sure it's because the database is not being created.
Is there any steps I can take to diagnose this problem or am I doing something wrong? I'm very new to this and I couldn't find any tutorials or info on publishing a database so I could be completely off base here.
When I run the seed method this is the SQL I'm seeing, notice there is no data being input for trivia:
CREATE TABLE [dbo].[TriviaAnswers] (
[QuestionId] [int] NOT NULL,
[OptionId] [int] NOT NULL,
[Id] [int] NOT NULL IDENTITY,
[UserId] [nvarchar](max),
CONSTRAINT [PK_dbo.TriviaAnswers] PRIMARY KEY ([Id])
)
CREATE TABLE [dbo].[TriviaOptions] (
[QuestionId] [int] NOT NULL,
[Id] [int] NOT NULL IDENTITY,
[Title] [nvarchar](max) NOT NULL,
[IsCorrect] [bit] NOT NULL,
CONSTRAINT [PK_dbo.TriviaOptions] PRIMARY KEY ([QuestionId], [Id])
)
CREATE TABLE [dbo].[TriviaQuestions] (
[Id] [int] NOT NULL IDENTITY,
[ImageClip] [nvarchar](max),
[ImageDir] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_dbo.TriviaQuestions] PRIMARY KEY ([Id])
)
CREATE INDEX [IX_QuestionId_OptionId] ON [dbo].[TriviaAnswers]([QuestionId], [OptionId])
CREATE INDEX [IX_QuestionId] ON [dbo].[TriviaOptions]([QuestionId])
ALTER TABLE [dbo].[TriviaAnswers] ADD CONSTRAINT [FK_dbo.TriviaAnswers_dbo.TriviaOptions_QuestionId_OptionId] FOREIGN KEY ([QuestionId], [OptionId]) REFERENCES [dbo].[TriviaOptions] ([QuestionId], [Id]) ON DELETE CASCADE
ALTER TABLE [dbo].[TriviaOptions] ADD CONSTRAINT [FK_dbo.TriviaOptions_dbo.TriviaQuestions_QuestionId] FOREIGN KEY ([QuestionId]) REFERENCES [dbo].[TriviaQuestions] ([Id]) ON DELETE CASCADE
CREATE TABLE [dbo].[__MigrationHistory] (
[MigrationId] [nvarchar](150) NOT NULL,
[ContextKey] [nvarchar](300) NOT NULL,
[Model] [varbinary](max) NOT NULL,
[ProductVersion] [nvarchar](32) NOT NULL,
CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey])
)
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201509240441274_AutomaticMigration', N'GeekQuiz.Models.TriviaContext', 0x1F8B0800000000000400ED5ADD6EDB3614BE1FB0771074B50DA915A7375B60B7489DA408D6246DEC16BB0B68E9D8214A511A496576873DD92EF6487B851DFD4BD48F253B4ED262C84D4CF3FCF0F07C3CE477FCEFDFFF8C5EAF5C66DC8390D4[snip (lots of stuff here)] , N'6.1.1-30610')

How can I stop ASP.NET Identity from Deleting a role if there's a UserId that has that role?

Here is the SQL for the tables:
CREATE TABLE [dbo].[AspNetUserRoles] (
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserRoles] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [dbo].[AspNetRoles] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (256) NOT NULL,
CONSTRAINT [PK_dbo.AspNetRoles] PRIMARY KEY CLUSTERED ([Id] ASC)
);
CREATE TABLE [dbo].[AspNetUsers] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[FirstName] NVARCHAR (MAX) NULL,
[LastName] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
ON [dbo].[AspNetUsers]([UserName] ASC);
Can someone help me. What I would like is for when there is a user that has been assigned to a role then I would like an attempt to delete the role to fail.
Your issue arises from the line ON DELETE CASCADE.
This line means that all records with foreign keys that connect to the record to be deleted will themselves be deleted.
You probably want ON DELETE NO ACTION. This will do what you want. You should be able to find whether anything was deleted by the return value of the query call (- It should be an integer containing the number of lines changed).

InvalidOperationException for MVC website but not WCF services

I have 3 projects:
WCF Services (Services)
MVC 5 Website (Website)
Class Library (Library)
I've installed Entity Framework v6.0.0.0 on all projects.
In my library I've enabled code migrations and added the domain models, DTOs, a couple of view models and a data access layer, one query/DAL looks like so:
public class WebsiteLayer {
EntitiesContext db;
public WebsiteLayer()
: this(new EntitiesContext()) { }
public WebsiteLayer(EntitiesContext _db) {
db = _db;
}
public List<ItemViewModel> GetStuff() {
return (from i in db.Items.Include(x => x.Inventory)
select new ItemViewModel() {
ID = i.ID,
Name = i.Name,
Qty = i.Inventory.Sum(x => x.Qty)
}).ToList();
}
}
So I use the same line of code in both my Services and Website projects:
WebsiteLayer dal = new WebsiteLayer();
var test = dal.GetStuff();
When this code is run in the Services everything works fine and I get my list of projected viewmodels back from the method. Top job.
When I run this code on my Website it flops and tells me the backing model has changed with an InvalidOperationException. What the hell?
So to summarise the shared library works for the WCF services project but not the MVC website project.
All projects have the same version of EF installed, the connection string exists in each of the relevant config files.
I did initially create the database using the Services but I've since deleted the DB and migrations and ran add-migration InitialCreate and update-database from the website. The website project has been able to successfully create a DB in the right location and the Services can successfully get information from there, but the website still states that the backing model has changed.
What could this be?
Edit 1:
I've ran a clean Update-Database -verbose command in the package manager console each time deleting the database and both outputs are the same:
CREATE TABLE [dbo].[Inventories] (
[ID] [int] NOT NULL IDENTITY,
[Qty] [int] NOT NULL,
[LocationID] [int] NOT NULL,
[ItemID] [int] NOT NULL,
CONSTRAINT [PK_dbo.Inventories] PRIMARY KEY ([ID])
)
CREATE INDEX [IX_LocationID] ON [dbo].[Inventories]([LocationID])
CREATE INDEX [IX_ItemID] ON [dbo].[Inventories]([ItemID])
CREATE TABLE [dbo].[Items] (
[ID] [int] NOT NULL IDENTITY,
[Code] [nvarchar](max),
[RefCode] [nvarchar](max),
[Name] [nvarchar](max),
[CreatedOn] [datetime] NOT NULL,
[UOM] [nvarchar](max),
[UnitOfMeasureID] [int] NOT NULL,
CONSTRAINT [PK_dbo.Items] PRIMARY KEY ([ID])
)
CREATE INDEX [IX_UnitOfMeasureID] ON [dbo].[Items]([UnitOfMeasureID])
CREATE TABLE [dbo].[UnitOfMeasures] (
[ID] [int] NOT NULL IDENTITY,
[Name] [nvarchar](max),
[SortOrder] [int] NOT NULL,
CONSTRAINT [PK_dbo.UnitOfMeasures] PRIMARY KEY ([ID])
)
CREATE TABLE [dbo].[Locations] (
[ID] [int] NOT NULL IDENTITY,
[Name] [nvarchar](max),
[Code] [nvarchar](max),
CONSTRAINT [PK_dbo.Locations] PRIMARY KEY ([ID])
)
ALTER TABLE [dbo].[Inventories] ADD CONSTRAINT [FK_dbo.Inventories_dbo.Items_ItemID] FOREIGN KEY ([ItemID]) REFERENCES [dbo].[Items] ([ID]) ON DELETE CASCADE
ALTER TABLE [dbo].[Inventories] ADD CONSTRAINT [FK_dbo.Inventories_dbo.Locations_LocationID] FOREIGN KEY ([LocationID]) REFERENCES [dbo].[Locations] ([ID]) ON DELETE CASCADE
ALTER TABLE [dbo].[Items] ADD CONSTRAINT [FK_dbo.Items_dbo.UnitOfMeasures_UnitOfMeasureID] FOREIGN KEY ([UnitOfMeasureID]) REFERENCES [dbo].[UnitOfMeasures] ([ID]) ON DELETE CASCADE
CREATE TABLE [dbo].[__MigrationHistory] (
[MigrationId] [nvarchar](150) NOT NULL,
[ContextKey] [nvarchar](300) NOT NULL,
[Model] [varbinary](max) NOT NULL,
[ProductVersion] [nvarchar](32) NOT NULL,
CONSTRAINT [PK_dbo.__MigrationHistory] PRIMARY KEY ([MigrationId], [ContextKey])
)
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'201406021411556_InitialCreate', N'InventoryLibrary.Migrations.Configuration', 0x1F8B0800000000000400ED5BDD6EDB3614BE1FB0771074B50DA995B4375D60B7C8EC643096C4699C14BB2B1889768849942652818D614FB68B3DD25E6147FF1449FDD9B19D164181A2A6787E78F8F1F0901FFBDF3FFF0E3FAE3CD778C221233E1D99278363D3C0D4F61D42972333E28B37EFCD8F1FBEFF6E78EE782BE373DEEF5DDC0F24291B998F9C07A796C5EC47EC2136F0881DFACC5FF081ED7B16727CEBEDF1F1CFD6C98985418509BA0C63781B514E3C9CFC809F639FDA38E01172AF7C07BB2C6B872FF344AB718D3CCC0264E39139A54F98723F5C5F928710856BD3387309023FE6D85D9806A2D4E7888397A7F70CCF79E8D3E53C8006E4DEAD030CFD16C86538F3FEB4ECDE7520C76FE38158A560AECA8E18F7BD9E0A4FDE6591B164F18DE26B169183D89D438CF93A1E75123F2174A6215B3B1DBB61DC538DEF6002FD084D2766507C3D32E48E47053C0045F19F23631CB93C0AF188E28887C83D326EA20797D8BFE1F59DFF07A6231AB9AEE832380DDF2A0DD07413FA010EF9FA162FF2814C4CC3AACA59B2602126C8E423E4EFDE9AC63518470F2E2E102144630EE3C2BF628A43C4B1738338C7214CE8D4C1494C15EB92AD4F71976663CD0A2E7D3B71A4DDE9663D538EBDDE3AAED1135926E635DA4CE316BBC947F6488274D50DE20F5F04745D84BE77EBBB9948F9E5CB1D0A9798833FBEF6F3DC8F42BB87437998B44EE51FF58EA95F15E7345D740E0EAD72A1352FBF247C1BAF3C907E5D740DB6C610A7DC1AE47DD8C04CE30AAD2E315DF2C79109FF84F9272BECE42D9907F794C07E07423C8C5A171484632F76E2BF776E641CE238D2339A5B9AC0CF3B125BEE9967EE67573BF7163AF3D9E20A2306E87EC6A45666876D325B9E196A325B9E5BBA7A55196CBD675237C9BBCA57BD87D52E3A2F3BA737C9974DF35C45CD6BC23B748E98FB219F850E0EFBACB7CE982937F04DE1926B7845CAA191B29B7D71C3BCDDBBF893B363437DD805E9678CF936493408D59FE04D7594E7D4319AB79534AC79E287C802944900E005E3706E376590CEE804BB9863E3CC4E0FA363C46CE4A8018601381D9D290A64C19932BC558F7E520CC172C1618C57E4C2799FC1022494AB6B8B509B04C86D0C8724D5714DC6832DF4CB5F2638C0345E4E8D43EF64383B73A9C60B1BD20CB44566680970EA80B2EA4EDC38B935254233DAD4B96DD4AA818D542BEC10CC9BA34E3B887D214F3B2F5D8C2B55F24160A849BF758069CAC52560CA42612F89AFE976607FC9AF3E347B80617D08BA18172FB0F680C0741306190E1238CC9C485A0966713B5E714D9179CF705667B2ACFE901111EB9D63AE161DE5BEAFA241C98E921658E14CA721C9B52DC29505AED322E5D61675F944E934958B4E5222CC42755462B92574D21FA66558B4164185EF45081568B5D62EA28EDA09B3AA03EC3A7829F2350168D89DBBEECFFD03A1DF91053D32ACB68E88AE025723D2B65174DD2A849108886E884A4386DF1222F991A0C846259B65A574564E7B5935BCD7F00A05019C9F041E2C6B31E62909367E33EFCF0F79A90ECB661A9AA8F0B6B004C3464B2C7D4D8F791724647C82387A40F1096EEC784A3739F7D664A1DC9A9C5ED589CB73532E11FF5B92CA2F086AD59481BC80B179F166979CACB533AEC82674247251A839C98F7D37F268FDC65B2F9D7045A2F827F53CDF242FEEB4A29AA61DB8612CD9E1A5329E9A034D8C60299CCA4EAFCC9B52835581D00D2649CEDB0E22F156BB013AB462BB01467A9F22CAA72DDD35146485A8A468ECAE27BD3E1295A42D3DC652320D950195CDDD75255C83A82569E8212F9F902ABADA8E4F0703BDB4416F85FEC612A4C3326891DFCD7AD81E85C25DB6A846687E31B35D16315B4D7451C1F79FE37AD1973ABDDD13E64E2755A9FFE42E85F5A20E94EABD61567BB53F86528AB1B48B6940689E88131762F335834D6B107718CCFF74C72E81F1961DAE10250BCC784A8098502BBE975E54BD9CD74D16638EABA95DB54F9CF64EE39038ACAD444D4F625D784994E8DFFA1D51A245B907995207AF46E65F89D8A931FDFD4B29796424C9F1D43836FEDEF2015257E3A9540FC3FDDEE07C1BD010F936FA8442FB11853F7868F5A3A86983372D5BE91299C6AD14296F531CF8C9B77C9BB2954735EF4FBA625A12DF05B89B789FAF15E5CF0628E521437B3EEDFF8CE135E6CF91A27642AA1F8C432FAF10F7CC9BEF85AC6CB86AFB7AA971E922FF20C4754FF43E136EDA6E0676C2767FDBC4F62179ECC3249F865B870327A017414BAB0C4ACD95503FD2393DFA43A1FCE0C36CA77B6BFE9968283D1D2B5D4B4A6B95EBA8C766BEBA9DAED6196AE126EB28ED46465B67A79639DC0BE1ADD0BACDACAE0C8AAF81D2D6624173A3DC4667B786EA65F1D55A7A7A4FB3DB838D566F1D21F509FF5113722F23CB5245FCDF3629B62B49AFE833A50B3FCFBF92477917E9B070853982433E3A0B3959209BC3671B3396BC23FE8CDC08BA9C7B0FD899D259C48388C390B1F7E0568211E7F026FB09E55EF579380B9235FF1C430037497C4F31A3BF44C4750ABF2F3467CB1A15F1E6901DE5E2B9E4F1916EB92E345DFBB4A3A22C7CC59E7687BDC005656C46E7E8096FE2DB3DC3977889EC757E795CAFA47D22AA611F4E085A86C863998E521E7E02861D6FF5E17FCB7A6653AF3C0000 , N'6.1.0-30225')

Select error on EF using existing master detail database

Entity Framework v5 looks cool and I try to switch from Linq-to-SQL with existing MSSQL (Azure) database.
but tutorials about EF are too complex to follow.
The database schema is pretty simple as follows (generated by exist db).
Sheets and SheetDetails tables are connected with 1-to-many relationship.
CREATE TABLE [dbo].[Sheets] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Grade] FLOAT (53) CONSTRAINT [DF_Sheets_Grade] DEFAULT ((0)) NOT NULL,
[Title] NVARCHAR (255) CONSTRAINT [DF_Sheets_Title] DEFAULT ('') NOT NULL,
[Description] NVARCHAR (255) NULL,
[Difficulty] SMALLINT CONSTRAINT [DF_Sheets_Difficulty] DEFAULT ((0)) NOT NULL,
[Writer] NVARCHAR (255) CONSTRAINT [DF_Sheets_Writer] DEFAULT ('') NOT NULL,
[Tag] NVARCHAR (255) NULL,
[Duration] FLOAT (53) CONSTRAINT [DF_Sheets_Duration] DEFAULT ((0)) NOT NULL,
[Timestamp] DATETIME CONSTRAINT [DF_Sheets_Timestamp] DEFAULT ((0)) NOT NULL,
[RowVersion] ROWVERSION NOT NULL,
CONSTRAINT [PK_Sheets] PRIMARY KEY CLUSTERED ([Id] ASC)
);
CREATE TABLE [dbo].[SheetDetails] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Score] FLOAT (53) CONSTRAINT [DF_SheetDetails_Score] DEFAULT ((0)) NOT NULL,
[Number] SMALLINT CONSTRAINT [DF_SheetDetails_Number] DEFAULT ((0)) NOT NULL,
[SubNumer] SMALLINT NULL,
[IsRandom] BIT CONSTRAINT [DF_SheetDetails_IsRandom] DEFAULT ((0)) NOT NULL,
[AnswerType] SMALLINT CONSTRAINT [DF_SheetDetails_AnswerType] DEFAULT ((0)) NOT NULL,
[RowVersion] ROWVERSION NOT NULL,
[SheetDetail_Sheet] INT CONSTRAINT [DF_SheetDetails_SheetDetail_Sheet] DEFAULT ((0)) NOT NULL,
[SheetDetail_Question] INT CONSTRAINT [DF_SheetDetails_SheetDetail_Question] DEFAULT ((0)) NOT NULL,
CONSTRAINT [SheetDetail_Sheet] FOREIGN KEY ([SheetDetail_Sheet]) REFERENCES [dbo].[Sheets] ([Id]) ON DELETE CASCADE
);
Note that the FK name is SheetDetail_Sheet in SheetDetails table.
Result diagram is as below.
Next, maybe I need to write EntityTypeConfiguration.
I tried it as question 1.
Question 1.
I wrote model creating configuration as follows but no luck. is it wrong? hard to know how to write right configuration with this simple database model.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new SheetsConfiguration());
base.OnModelCreating(modelBuilder);
}
public class SheetsConfiguration : EntityTypeConfiguration<Sheets>
{
public SheetsConfiguration()
: base()
{
HasKey(p => p.Id);
Property(p => p.Id).HasColumnName("Id").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
Property(p => p.RowVersion).IsConcurrencyToken().IsRowVersion();
HasOptional(p => p.SheetDetails).WithMany().Map(x => x.MapKey("SheetDetail_Sheet"));
ToTable("Sheets");
}
}
I execute simple query using
var result = _db.Sheets.Where(sheet => sheet.Id == id).ToList();
And then, I got an error "Invalid column name SheetDetail_Sheet" with executed query as follows.
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Grade] AS [Grade],
[Extent1].[Title] AS [Title],
[Extent1].[Description] AS [Description],
[Extent1].[Difficulty] AS [Difficulty],
[Extent1].[Writer] AS [Writer],
[Extent1].[Tag] AS [Tag],
[Extent1].[Duration] AS [Duration],
[Extent1].[Timestamp] AS [Timestamp],
[Extent1].[RowVersion] AS [RowVersion],
[Extent1].[SheetDetail_Sheet] AS [SheetDetail_Sheet]
FROM [dbo].[Sheets] AS [Extent1]
WHERE [Extent1].[Id] = #p__linq__0
I can understand because SheetDetail_Sheet is just an FK and not exist in the edmx properties and database column.
How can I fix it?
I don't want to edit auto-generated model file because it can be overwritten. maybe it seems to be achieved with EntityTypeConfiguration.
Question 2.
Is there any useful and lightweight reference with the commonly used master-detail database model?
I'm in trouble to start with existing database.
stackoverflow, asp.net, blogs, etc...to many tutorials but hard to find an example like my case.
Thank you.
I'd suggest using Model First to create your database model (though you're using database first). A good article for getting the database model is here. Just ignore the MVC stuff, and stop at "Generating Strongly Typed Entity Classes" as you are using EF5 which will generate the POCO classes for you. The Edmx should handle all of the FKs and properties for you and you won't need to worry about the configurator.

Categories