EF的代码优先,如何定义导航属性关系而无需在数据库中的表之间设置外键

时间:2016-02-19 09:17:28

标签: c# asp.net entity-framework

我首先使用Entity框架的代码。有两个课程"问题"和"用户"。我定义了如下关系:

{{1}}

在生成数据库之后,我发现它总是在用户的Id和问题的CreatorId之间创建外键。由于FK性能较低(以及其他原因),我想在不设置数据库外键的情况下定义导航属性关系? EF创建后删除FK? 如果不能用流畅的api做到这一点,你能告诉我为什么用这种方式设计EF吗?

关于FK的较低性能。我有一个包含500万条记录的用户表。当我在db中插入一个Question时,由于db检查来自User表的问题.CreatorId验证,它总是慢于没有FK。 还有很多其他原因我需要删除FK。

我认为我有点迷恋,因为我认为在创建它之后删除FK是奇怪和丑陋的。我想要的是通过在流畅的api中使用像WithoutForeignKey这样的东西来实现它:

{{1}}

3 个答案:

答案 0 :(得分:1)

没有质疑你为什么要尝试做这个奇怪的事情而只是回答:你可以在生成之后删除fk约束,或者你可以使用迁移并从迁移代码中删除FK生成。

当遍历导航属性时生成的SQL代码即使fk约束不存在也会起作用,但级联删除除外

答案 1 :(得分:0)

如果需要两个表之间的关系,则需要定义外键。没办法解决它。即使您在流畅的api中使用Map(),您也只能隐藏模型中的外键,在后台EF仍然会使用它,它将存在于数据库中。

另外,我不明白外键的“性能”是什么意思?一个额外的(可能很小的)列不会有所作为。如果您指的是性能部件的导航属性,则可以执行以下三项操作:

  1. 不要将它们包含在您的模型中
  2. 将它们设为非虚拟以禁用延迟加载
  3. ctx.Configuration.LazyLoadingEnabled = false;
  4. 一起禁用延迟加载

答案 2 :(得分:0)

如果你不想告诉db关于关系并将两个实体视为不相关(我想知道为什么),那么只需要ignore这些导航属性和FK字段。请注意,您将负责管理相关实体:从db保存和加载它们,更新ID等

Creator_CreatorId

您还需要忽略关系的其他方面,否则EF将生成默认名称为Creator的FK列。所以在this.Ignore(c => c.Questiones); 实体配置中:

directivesApp.directive('bindTimestamp', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {

            var minDate = attrs.min ? new Date(attrs.min) : null;
            var maxDate = attrs.max ? new Date(attrs.max) : null;

            ngModel.$formatters.push(function (value) {
                var dt = value;
                if (!angular.isDate(dt) && angular.isNumber(dt)) {
                    // It's a timestamp --> needs to be converted to a <Date>
                    dt = new Date(value);
                }
                // truncate 'dt' to second if milliseconds are not to be displayed in input[datetime-local]
                // dt.setMilliSeconds(0);
                // truncate 'dt' to minute if seconds are not to be displayed in input[datetime-local]
                // dt.setSeconds(0);
                return dt;
            });

            // Default validators need to be overriden, otherwise they will always trigger "false" as they expect a <Date> object and not a number.
            var MinMaxValidator = function (modelValue) {
                var selectedDate = angular.timestampToDate(modelValue, scope.truncateSeconds);
                this.validate = function (validateThreshold) {
                    if (angular.isDate(selectedDate)) {
                        return validateThreshold(selectedDate);
                    }
                    return true;
                };
            };

            if (ngModel.$validators.min && minDate !== null) {
                ngModel.$validators.min = function (modelValue) {
                    return new MinMaxValidator(modelValue).validate(function (selectedDate) {
                        return minDate <= selectedDate;
                    });
                };
            }

            if (ngModel.$validators.max && maxDate !== null) {
                ngModel.$validators.max = function (modelValue) {
                    return new MinMaxValidator(modelValue).validate(function (selectedDate) {
                        return maxDate >= selectedDate;
                    });
                };
            }
        }
    };
});